1 /**************************************************************************** 2 * 3 * gxvmorx.c 4 * 5 * TrueTypeGX/AAT morx table validation (body). 6 * 7 * Copyright (C) 2005-2019 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 gxvmorx 39 40 41 static void gxv_morx_subtables_validate(FT_Bytes table,FT_Bytes limit,FT_UShort nSubtables,GXV_Validator gxvalid)42 gxv_morx_subtables_validate( FT_Bytes table, 43 FT_Bytes limit, 44 FT_UShort nSubtables, 45 GXV_Validator gxvalid ) 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 gxvalid ); 97 if ( type > 5 ) 98 FT_INVALID_FORMAT; 99 100 func = fmt_funcs_table[type]; 101 if ( !func ) 102 GXV_TRACE(( "morx type %d is reserved\n", type )); 103 104 func( p, p + rest, gxvalid ); 105 106 /* TODO: subFeatureFlags should be unique in a table? */ 107 p += rest; 108 } 109 110 gxvalid->subtable_length = (FT_ULong)( p - table ); 111 112 GXV_EXIT; 113 } 114 115 116 static void gxv_morx_chain_validate(FT_Bytes table,FT_Bytes limit,GXV_Validator gxvalid)117 gxv_morx_chain_validate( FT_Bytes table, 118 FT_Bytes limit, 119 GXV_Validator gxvalid ) 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, gxvalid ); 144 p += gxvalid->subtable_length; 145 146 if ( nSubtables >= 0x10000L ) 147 FT_INVALID_DATA; 148 149 gxv_morx_subtables_validate( p, table + chainLength, 150 (FT_UShort)nSubtables, gxvalid ); 151 152 gxvalid->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 gxvalidrec; 166 GXV_Validator gxvalid = &gxvalidrec; 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 gxvalid->root = ftvalid; 175 gxvalid->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, gxvalid ); 192 p += gxvalid->subtable_length; 193 } 194 195 FT_TRACE4(( "\n" )); 196 } 197 198 199 /* END */ 200