1 /***************************************************************************/ 2 /* */ 3 /* gxvmorx.c */ 4 /* */ 5 /* TrueTypeGX/AAT morx table validation (body). */ 6 /* */ 7 /* Copyright 2005, 2008, 2013 by */ 8 /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ 9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 10 /* */ 11 /* This file is part of the FreeType project, and may only be used, */ 12 /* modified, and distributed under the terms of the FreeType project */ 13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 14 /* this file you indicate that you have read the license and */ 15 /* understand and accept it fully. */ 16 /* */ 17 /***************************************************************************/ 18 19 /***************************************************************************/ 20 /* */ 21 /* gxvalid is derived from both gxlayout module and otvalid module. */ 22 /* Development of gxlayout is supported by the Information-technology */ 23 /* Promotion Agency(IPA), Japan. */ 24 /* */ 25 /***************************************************************************/ 26 27 28 #include "gxvmorx.h" 29 30 31 /*************************************************************************/ 32 /* */ 33 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 34 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 35 /* messages during execution. */ 36 /* */ 37 #undef FT_COMPONENT 38 #define FT_COMPONENT trace_gxvmorx 39 40 41 static void gxv_morx_subtables_validate(FT_Bytes table,FT_Bytes limit,FT_UShort nSubtables,GXV_Validator valid)42 gxv_morx_subtables_validate( FT_Bytes table, 43 FT_Bytes limit, 44 FT_UShort nSubtables, 45 GXV_Validator valid ) 46 { 47 FT_Bytes p = table; 48 49 GXV_Validate_Func fmt_funcs_table[] = 50 { 51 gxv_morx_subtable_type0_validate, /* 0 */ 52 gxv_morx_subtable_type1_validate, /* 1 */ 53 gxv_morx_subtable_type2_validate, /* 2 */ 54 NULL, /* 3 */ 55 gxv_morx_subtable_type4_validate, /* 4 */ 56 gxv_morx_subtable_type5_validate, /* 5 */ 57 58 }; 59 60 FT_UShort i; 61 62 63 GXV_NAME_ENTER( "subtables in a chain" ); 64 65 for ( i = 0; i < nSubtables; i++ ) 66 { 67 GXV_Validate_Func func; 68 69 FT_ULong length; 70 FT_ULong coverage; 71 #ifdef GXV_LOAD_UNUSED_VARS 72 FT_ULong subFeatureFlags; 73 #endif 74 FT_ULong type; 75 FT_ULong rest; 76 77 78 GXV_LIMIT_CHECK( 4 + 4 + 4 ); 79 length = FT_NEXT_ULONG( p ); 80 coverage = FT_NEXT_ULONG( p ); 81 #ifdef GXV_LOAD_UNUSED_VARS 82 subFeatureFlags = FT_NEXT_ULONG( p ); 83 #else 84 p += 4; 85 #endif 86 87 GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n", 88 i + 1, nSubtables, length )); 89 90 type = coverage & 0x0007; 91 rest = length - ( 4 + 4 + 4 ); 92 GXV_LIMIT_CHECK( rest ); 93 94 /* morx coverage consists of mort_coverage & 16bit padding */ 95 gxv_mort_coverage_validate( (FT_UShort)( ( coverage >> 16 ) | coverage ), 96 valid ); 97 if ( type > 5 ) 98 FT_INVALID_FORMAT; 99 100 func = fmt_funcs_table[type]; 101 if ( func == NULL ) 102 GXV_TRACE(( "morx type %d is reserved\n", type )); 103 104 func( p, p + rest, valid ); 105 106 /* TODO: subFeatureFlags should be unique in a table? */ 107 p += rest; 108 } 109 110 valid->subtable_length = p - table; 111 112 GXV_EXIT; 113 } 114 115 116 static void gxv_morx_chain_validate(FT_Bytes table,FT_Bytes limit,GXV_Validator valid)117 gxv_morx_chain_validate( FT_Bytes table, 118 FT_Bytes limit, 119 GXV_Validator valid ) 120 { 121 FT_Bytes p = table; 122 #ifdef GXV_LOAD_UNUSED_VARS 123 FT_ULong defaultFlags; 124 #endif 125 FT_ULong chainLength; 126 FT_ULong nFeatureFlags; 127 FT_ULong nSubtables; 128 129 130 GXV_NAME_ENTER( "morx chain header" ); 131 132 GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 ); 133 #ifdef GXV_LOAD_UNUSED_VARS 134 defaultFlags = FT_NEXT_ULONG( p ); 135 #else 136 p += 4; 137 #endif 138 chainLength = FT_NEXT_ULONG( p ); 139 nFeatureFlags = FT_NEXT_ULONG( p ); 140 nSubtables = FT_NEXT_ULONG( p ); 141 142 /* feature-array of morx is same with that of mort */ 143 gxv_mort_featurearray_validate( p, limit, nFeatureFlags, valid ); 144 p += valid->subtable_length; 145 146 if ( nSubtables >= 0x10000L ) 147 FT_INVALID_DATA; 148 149 gxv_morx_subtables_validate( p, table + chainLength, 150 (FT_UShort)nSubtables, valid ); 151 152 valid->subtable_length = chainLength; 153 154 /* TODO: defaultFlags should be compared with the flags in tables */ 155 156 GXV_EXIT; 157 } 158 159 160 FT_LOCAL_DEF( void ) gxv_morx_validate(FT_Bytes table,FT_Face face,FT_Validator ftvalid)161 gxv_morx_validate( FT_Bytes table, 162 FT_Face face, 163 FT_Validator ftvalid ) 164 { 165 GXV_ValidatorRec validrec; 166 GXV_Validator valid = &validrec; 167 FT_Bytes p = table; 168 FT_Bytes limit = 0; 169 FT_ULong version; 170 FT_ULong nChains; 171 FT_ULong i; 172 173 174 valid->root = ftvalid; 175 valid->face = face; 176 177 FT_TRACE3(( "validating `morx' table\n" )); 178 GXV_INIT; 179 180 GXV_LIMIT_CHECK( 4 + 4 ); 181 version = FT_NEXT_ULONG( p ); 182 nChains = FT_NEXT_ULONG( p ); 183 184 if ( version != 0x00020000UL ) 185 FT_INVALID_FORMAT; 186 187 for ( i = 0; i < nChains; i++ ) 188 { 189 GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains )); 190 GXV_32BIT_ALIGNMENT_VALIDATE( p - table ); 191 gxv_morx_chain_validate( p, limit, valid ); 192 p += valid->subtable_length; 193 } 194 195 FT_TRACE4(( "\n" )); 196 } 197 198 199 /* END */ 200