00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "gxvmorx.h"
00029
00030
00031
00032
00033
00034
00035
00036
00037 #undef FT_COMPONENT
00038 #define FT_COMPONENT trace_gxvmorx
00039
00040
00041 static void
00042 gxv_morx_subtables_validate( FT_Bytes table,
00043 FT_Bytes limit,
00044 FT_UShort nSubtables,
00045 GXV_Validator valid )
00046 {
00047 FT_Bytes p = table;
00048
00049 GXV_Validate_Func fmt_funcs_table[] =
00050 {
00051 gxv_morx_subtable_type0_validate,
00052 gxv_morx_subtable_type1_validate,
00053 gxv_morx_subtable_type2_validate,
00054 NULL,
00055 gxv_morx_subtable_type4_validate,
00056 gxv_morx_subtable_type5_validate,
00057
00058 };
00059
00060 GXV_Validate_Func func;
00061
00062 FT_UShort i;
00063
00064
00065 GXV_NAME_ENTER( "subtables in a chain" );
00066
00067 for ( i = 0; i < nSubtables; i++ )
00068 {
00069 FT_ULong length;
00070 FT_ULong coverage;
00071 FT_ULong subFeatureFlags;
00072 FT_ULong type;
00073 FT_ULong rest;
00074
00075
00076 GXV_LIMIT_CHECK( 4 + 4 + 4 );
00077 length = FT_NEXT_ULONG( p );
00078 coverage = FT_NEXT_ULONG( p );
00079 subFeatureFlags = FT_NEXT_ULONG( p );
00080
00081 GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
00082 i + 1, nSubtables, length ));
00083
00084 type = coverage & 0x0007;
00085 rest = length - ( 4 + 4 + 4 );
00086 GXV_LIMIT_CHECK( rest );
00087
00088
00089 gxv_mort_coverage_validate( (FT_UShort)( ( coverage >> 16 ) | coverage ),
00090 valid );
00091 if ( type > 5 )
00092 FT_INVALID_FORMAT;
00093
00094 func = fmt_funcs_table[type];
00095 if ( func == NULL )
00096 GXV_TRACE(( "morx type %d is reserved\n", type ));
00097
00098 func( p, p + rest, valid );
00099
00100 p += rest;
00101 }
00102
00103 valid->subtable_length = p - table;
00104
00105 GXV_EXIT;
00106 }
00107
00108
00109 static void
00110 gxv_morx_chain_validate( FT_Bytes table,
00111 FT_Bytes limit,
00112 GXV_Validator valid )
00113 {
00114 FT_Bytes p = table;
00115 FT_ULong defaultFlags;
00116 FT_ULong chainLength;
00117 FT_ULong nFeatureFlags;
00118 FT_ULong nSubtables;
00119
00120
00121 GXV_NAME_ENTER( "morx chain header" );
00122
00123 GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
00124 defaultFlags = FT_NEXT_ULONG( p );
00125 chainLength = FT_NEXT_ULONG( p );
00126 nFeatureFlags = FT_NEXT_ULONG( p );
00127 nSubtables = FT_NEXT_ULONG( p );
00128
00129
00130 gxv_mort_featurearray_validate( p, limit, nFeatureFlags, valid );
00131 p += valid->subtable_length;
00132
00133 if ( nSubtables >= 0x10000L )
00134 FT_INVALID_DATA;
00135
00136 gxv_morx_subtables_validate( p, table + chainLength,
00137 (FT_UShort)nSubtables, valid );
00138
00139 valid->subtable_length = chainLength;
00140
00141 GXV_EXIT;
00142 }
00143
00144
00145 FT_LOCAL_DEF( void )
00146 gxv_morx_validate( FT_Bytes table,
00147 FT_Face face,
00148 FT_Validator ftvalid )
00149 {
00150 GXV_ValidatorRec validrec;
00151 GXV_Validator valid = &validrec;
00152 FT_Bytes p = table;
00153 FT_Bytes limit = 0;
00154 FT_ULong version;
00155 FT_ULong nChains;
00156 FT_ULong i;
00157
00158
00159 valid->root = ftvalid;
00160 valid->face = face;
00161
00162 FT_TRACE3(( "validating `morx' table\n" ));
00163 GXV_INIT;
00164
00165 GXV_LIMIT_CHECK( 4 + 4 );
00166 version = FT_NEXT_ULONG( p );
00167 nChains = FT_NEXT_ULONG( p );
00168
00169 if ( version != 0x00020000UL )
00170 FT_INVALID_FORMAT;
00171
00172 for ( i = 0; i < nChains; i++ )
00173 {
00174 GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains ));
00175 GXV_32BIT_ALIGNMENT_VALIDATE( p - table );
00176 gxv_morx_chain_validate( p, limit, valid );
00177 p += valid->subtable_length;
00178 }
00179
00180 FT_TRACE4(( "\n" ));
00181 }
00182
00183
00184