1 /**************************************************************************** 2 * 3 * otvgdef.c 4 * 5 * OpenType GDEF table validation (body). 6 * 7 * Copyright (C) 2004-2020 by 8 * David Turner, Robert Wilhelm, and Werner Lemberg. 9 * 10 * This file is part of the FreeType project, and may only be used, 11 * modified, and distributed under the terms of the FreeType project 12 * license, LICENSE.TXT. By continuing to use, modify, or distribute 13 * this file you indicate that you have read the license and 14 * understand and accept it fully. 15 * 16 */ 17 18 19 #include "otvalid.h" 20 #include "otvcommn.h" 21 22 23 /************************************************************************** 24 * 25 * The macro FT_COMPONENT is used in trace mode. It is an implicit 26 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 27 * messages during execution. 28 */ 29 #undef FT_COMPONENT 30 #define FT_COMPONENT otvgdef 31 32 33 /*************************************************************************/ 34 /*************************************************************************/ 35 /***** *****/ 36 /***** UTILITY FUNCTIONS *****/ 37 /***** *****/ 38 /*************************************************************************/ 39 /*************************************************************************/ 40 41 #define AttachListFunc otv_O_x_Ox 42 #define LigCaretListFunc otv_O_x_Ox 43 44 /* sets valid->extra1 (0) */ 45 46 static void otv_O_x_Ox(FT_Bytes table,OTV_Validator otvalid)47 otv_O_x_Ox( FT_Bytes table, 48 OTV_Validator otvalid ) 49 { 50 FT_Bytes p = table; 51 FT_Bytes Coverage; 52 FT_UInt GlyphCount; 53 OTV_Validate_Func func; 54 55 56 OTV_ENTER; 57 58 OTV_LIMIT_CHECK( 4 ); 59 Coverage = table + FT_NEXT_USHORT( p ); 60 GlyphCount = FT_NEXT_USHORT( p ); 61 62 OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount )); 63 64 otv_Coverage_validate( Coverage, otvalid, (FT_Int)GlyphCount ); 65 if ( GlyphCount != otv_Coverage_get_count( Coverage ) ) 66 FT_INVALID_DATA; 67 68 OTV_LIMIT_CHECK( GlyphCount * 2 ); 69 70 otvalid->nesting_level++; 71 func = otvalid->func[otvalid->nesting_level]; 72 otvalid->extra1 = 0; 73 74 for ( ; GlyphCount > 0; GlyphCount-- ) 75 func( table + FT_NEXT_USHORT( p ), otvalid ); 76 77 otvalid->nesting_level--; 78 79 OTV_EXIT; 80 } 81 82 83 /*************************************************************************/ 84 /*************************************************************************/ 85 /***** *****/ 86 /***** LIGATURE CARETS *****/ 87 /***** *****/ 88 /*************************************************************************/ 89 /*************************************************************************/ 90 91 #define CaretValueFunc otv_CaretValue_validate 92 93 static void otv_CaretValue_validate(FT_Bytes table,OTV_Validator otvalid)94 otv_CaretValue_validate( FT_Bytes table, 95 OTV_Validator otvalid ) 96 { 97 FT_Bytes p = table; 98 FT_UInt CaretValueFormat; 99 100 101 OTV_ENTER; 102 103 OTV_LIMIT_CHECK( 4 ); 104 105 CaretValueFormat = FT_NEXT_USHORT( p ); 106 107 OTV_TRACE(( " (format = %d)\n", CaretValueFormat )); 108 109 switch ( CaretValueFormat ) 110 { 111 case 1: /* CaretValueFormat1 */ 112 /* skip Coordinate, no test */ 113 break; 114 115 case 2: /* CaretValueFormat2 */ 116 /* skip CaretValuePoint, no test */ 117 break; 118 119 case 3: /* CaretValueFormat3 */ 120 p += 2; /* skip Coordinate */ 121 122 OTV_LIMIT_CHECK( 2 ); 123 124 /* DeviceTable */ 125 otv_Device_validate( table + FT_NEXT_USHORT( p ), otvalid ); 126 break; 127 128 default: 129 FT_INVALID_FORMAT; 130 } 131 132 OTV_EXIT; 133 } 134 135 136 /*************************************************************************/ 137 /*************************************************************************/ 138 /***** *****/ 139 /***** MARK GLYPH SETS *****/ 140 /***** *****/ 141 /*************************************************************************/ 142 /*************************************************************************/ 143 144 static void otv_MarkGlyphSets_validate(FT_Bytes table,OTV_Validator otvalid)145 otv_MarkGlyphSets_validate( FT_Bytes table, 146 OTV_Validator otvalid ) 147 { 148 FT_Bytes p = table; 149 FT_UInt MarkGlyphSetCount; 150 151 152 OTV_NAME_ENTER( "MarkGlyphSets" ); 153 154 p += 2; /* skip Format */ 155 156 OTV_LIMIT_CHECK( 2 ); 157 MarkGlyphSetCount = FT_NEXT_USHORT( p ); 158 159 OTV_TRACE(( " (MarkGlyphSetCount = %d)\n", MarkGlyphSetCount )); 160 161 OTV_LIMIT_CHECK( MarkGlyphSetCount * 4 ); /* CoverageOffsets */ 162 163 for ( ; MarkGlyphSetCount > 0; MarkGlyphSetCount-- ) 164 otv_Coverage_validate( table + FT_NEXT_ULONG( p ), otvalid, -1 ); 165 166 OTV_EXIT; 167 } 168 169 170 /*************************************************************************/ 171 /*************************************************************************/ 172 /***** *****/ 173 /***** GDEF TABLE *****/ 174 /***** *****/ 175 /*************************************************************************/ 176 /*************************************************************************/ 177 178 /* sets otvalid->glyph_count */ 179 180 FT_LOCAL_DEF( void ) otv_GDEF_validate(FT_Bytes table,FT_Bytes gsub,FT_Bytes gpos,FT_UInt glyph_count,FT_Validator ftvalid)181 otv_GDEF_validate( FT_Bytes table, 182 FT_Bytes gsub, 183 FT_Bytes gpos, 184 FT_UInt glyph_count, 185 FT_Validator ftvalid ) 186 { 187 OTV_ValidatorRec otvalidrec; 188 OTV_Validator otvalid = &otvalidrec; 189 FT_Bytes p = table; 190 FT_UInt table_size; 191 FT_UShort version; 192 FT_Bool need_MarkAttachClassDef = 1; 193 194 OTV_OPTIONAL_TABLE( GlyphClassDef ); 195 OTV_OPTIONAL_TABLE( AttachListOffset ); 196 OTV_OPTIONAL_TABLE( LigCaretListOffset ); 197 OTV_OPTIONAL_TABLE( MarkAttachClassDef ); 198 OTV_OPTIONAL_TABLE( MarkGlyphSetsDef ); 199 200 OTV_OPTIONAL_TABLE32( itemVarStore ); 201 202 203 otvalid->root = ftvalid; 204 205 FT_TRACE3(( "validating GDEF table\n" )); 206 OTV_INIT; 207 208 OTV_LIMIT_CHECK( 4 ); 209 210 if ( FT_NEXT_USHORT( p ) != 1 ) /* majorVersion */ 211 FT_INVALID_FORMAT; 212 213 version = FT_NEXT_USHORT( p ); /* minorVersion */ 214 215 table_size = 10; 216 switch ( version ) 217 { 218 case 0: 219 /* MarkAttachClassDef has been added to the OpenType */ 220 /* specification without increasing GDEF's version, */ 221 /* so we use this ugly hack to find out whether the */ 222 /* table is needed actually. */ 223 224 need_MarkAttachClassDef = FT_BOOL( 225 otv_GSUBGPOS_have_MarkAttachmentType_flag( gsub ) || 226 otv_GSUBGPOS_have_MarkAttachmentType_flag( gpos ) ); 227 228 if ( need_MarkAttachClassDef ) 229 { 230 OTV_LIMIT_CHECK( 8 ); 231 table_size += 2; 232 } 233 else 234 OTV_LIMIT_CHECK( 6 ); /* OpenType < 1.2 */ 235 236 break; 237 238 case 2: 239 OTV_LIMIT_CHECK( 10 ); 240 table_size += 4; 241 break; 242 243 case 3: 244 OTV_LIMIT_CHECK( 14 ); 245 table_size += 8; 246 break; 247 248 default: 249 FT_INVALID_FORMAT; 250 } 251 252 otvalid->glyph_count = glyph_count; 253 254 OTV_OPTIONAL_OFFSET( GlyphClassDef ); 255 OTV_SIZE_CHECK( GlyphClassDef ); 256 if ( GlyphClassDef ) 257 otv_ClassDef_validate( table + GlyphClassDef, otvalid ); 258 259 OTV_OPTIONAL_OFFSET( AttachListOffset ); 260 OTV_SIZE_CHECK( AttachListOffset ); 261 if ( AttachListOffset ) 262 { 263 OTV_NEST2( AttachList, AttachPoint ); 264 OTV_RUN( table + AttachListOffset, otvalid ); 265 } 266 267 OTV_OPTIONAL_OFFSET( LigCaretListOffset ); 268 OTV_SIZE_CHECK( LigCaretListOffset ); 269 if ( LigCaretListOffset ) 270 { 271 OTV_NEST3( LigCaretList, LigGlyph, CaretValue ); 272 OTV_RUN( table + LigCaretListOffset, otvalid ); 273 } 274 275 if ( need_MarkAttachClassDef ) 276 { 277 OTV_OPTIONAL_OFFSET( MarkAttachClassDef ); 278 OTV_SIZE_CHECK( MarkAttachClassDef ); 279 if ( MarkAttachClassDef ) 280 otv_ClassDef_validate( table + MarkAttachClassDef, otvalid ); 281 } 282 283 if ( version > 0 ) 284 { 285 OTV_OPTIONAL_OFFSET( MarkGlyphSetsDef ); 286 OTV_SIZE_CHECK( MarkGlyphSetsDef ); 287 if ( MarkGlyphSetsDef ) 288 otv_MarkGlyphSets_validate( table + MarkGlyphSetsDef, otvalid ); 289 } 290 291 if ( version > 2 ) 292 { 293 OTV_OPTIONAL_OFFSET32( itemVarStore ); 294 OTV_SIZE_CHECK32( itemVarStore ); 295 if ( itemVarStore ) 296 OTV_TRACE(( " [omitting itemVarStore validation]\n" )); /* XXX */ 297 } 298 299 FT_TRACE4(( "\n" )); 300 } 301 302 303 /* END */ 304