00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "otvalid.h"
00020 #include "otvcommn.h"
00021
00022
00023
00024
00025
00026
00027
00028
00029 #undef FT_COMPONENT
00030 #define FT_COMPONENT trace_otvgsub
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 static void
00044 otv_SingleSubst_validate( FT_Bytes table,
00045 OTV_Validator valid )
00046 {
00047 FT_Bytes p = table;
00048 FT_UInt SubstFormat;
00049
00050
00051 OTV_NAME_ENTER( "SingleSubst" );
00052
00053 OTV_LIMIT_CHECK( 2 );
00054 SubstFormat = FT_NEXT_USHORT( p );
00055
00056 OTV_TRACE(( " (format %d)\n", SubstFormat ));
00057
00058 switch ( SubstFormat )
00059 {
00060 case 1:
00061 {
00062 FT_Bytes Coverage;
00063 FT_Int DeltaGlyphID;
00064 FT_Long idx;
00065
00066
00067 OTV_LIMIT_CHECK( 4 );
00068 Coverage = table + FT_NEXT_USHORT( p );
00069 DeltaGlyphID = FT_NEXT_SHORT( p );
00070
00071 otv_Coverage_validate( Coverage, valid, -1 );
00072
00073 idx = otv_Coverage_get_first( Coverage ) + DeltaGlyphID;
00074 if ( idx < 0 )
00075 FT_INVALID_DATA;
00076
00077 idx = otv_Coverage_get_last( Coverage ) + DeltaGlyphID;
00078 if ( (FT_UInt)idx >= valid->glyph_count )
00079 FT_INVALID_DATA;
00080 }
00081 break;
00082
00083 case 2:
00084 {
00085 FT_UInt Coverage, GlyphCount;
00086
00087
00088 OTV_LIMIT_CHECK( 4 );
00089 Coverage = FT_NEXT_USHORT( p );
00090 GlyphCount = FT_NEXT_USHORT( p );
00091
00092 OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
00093
00094 otv_Coverage_validate( table + Coverage, valid, GlyphCount );
00095
00096 OTV_LIMIT_CHECK( GlyphCount * 2 );
00097
00098
00099 for ( ; GlyphCount > 0; GlyphCount-- )
00100 if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
00101 FT_INVALID_GLYPH_ID;
00102 }
00103 break;
00104
00105 default:
00106 FT_INVALID_FORMAT;
00107 }
00108
00109 OTV_EXIT;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 static void
00124 otv_MultipleSubst_validate( FT_Bytes table,
00125 OTV_Validator valid )
00126 {
00127 FT_Bytes p = table;
00128 FT_UInt SubstFormat;
00129
00130
00131 OTV_NAME_ENTER( "MultipleSubst" );
00132
00133 OTV_LIMIT_CHECK( 2 );
00134 SubstFormat = FT_NEXT_USHORT( p );
00135
00136 OTV_TRACE(( " (format %d)\n", SubstFormat ));
00137
00138 switch ( SubstFormat )
00139 {
00140 case 1:
00141 valid->extra1 = valid->glyph_count;
00142 OTV_NEST2( MultipleSubstFormat1, Sequence );
00143 OTV_RUN( table, valid );
00144 break;
00145
00146 default:
00147 FT_INVALID_FORMAT;
00148 }
00149
00150 OTV_EXIT;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 static void
00165 otv_AlternateSubst_validate( FT_Bytes table,
00166 OTV_Validator valid )
00167 {
00168 FT_Bytes p = table;
00169 FT_UInt SubstFormat;
00170
00171
00172 OTV_NAME_ENTER( "AlternateSubst" );
00173
00174 OTV_LIMIT_CHECK( 2 );
00175 SubstFormat = FT_NEXT_USHORT( p );
00176
00177 OTV_TRACE(( " (format %d)\n", SubstFormat ));
00178
00179 switch ( SubstFormat )
00180 {
00181 case 1:
00182 valid->extra1 = valid->glyph_count;
00183 OTV_NEST2( AlternateSubstFormat1, AlternateSet );
00184 OTV_RUN( table, valid );
00185 break;
00186
00187 default:
00188 FT_INVALID_FORMAT;
00189 }
00190
00191 OTV_EXIT;
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 #define LigatureFunc otv_Ligature_validate
00204
00205
00206
00207 static void
00208 otv_Ligature_validate( FT_Bytes table,
00209 OTV_Validator valid )
00210 {
00211 FT_Bytes p = table;
00212 FT_UInt LigatureGlyph, CompCount;
00213
00214
00215 OTV_ENTER;
00216
00217 OTV_LIMIT_CHECK( 4 );
00218 LigatureGlyph = FT_NEXT_USHORT( p );
00219 if ( LigatureGlyph >= valid->glyph_count )
00220 FT_INVALID_DATA;
00221
00222 CompCount = FT_NEXT_USHORT( p );
00223
00224 OTV_TRACE(( " (CompCount = %d)\n", CompCount ));
00225
00226 if ( CompCount == 0 )
00227 FT_INVALID_DATA;
00228
00229 CompCount--;
00230
00231 OTV_LIMIT_CHECK( CompCount * 2 );
00232
00233
00234
00235 OTV_EXIT;
00236 }
00237
00238
00239 static void
00240 otv_LigatureSubst_validate( FT_Bytes table,
00241 OTV_Validator valid )
00242 {
00243 FT_Bytes p = table;
00244 FT_UInt SubstFormat;
00245
00246
00247 OTV_NAME_ENTER( "LigatureSubst" );
00248
00249 OTV_LIMIT_CHECK( 2 );
00250 SubstFormat = FT_NEXT_USHORT( p );
00251
00252 OTV_TRACE(( " (format %d)\n", SubstFormat ));
00253
00254 switch ( SubstFormat )
00255 {
00256 case 1:
00257 OTV_NEST3( LigatureSubstFormat1, LigatureSet, Ligature );
00258 OTV_RUN( table, valid );
00259 break;
00260
00261 default:
00262 FT_INVALID_FORMAT;
00263 }
00264
00265 OTV_EXIT;
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 static void
00280 otv_ContextSubst_validate( FT_Bytes table,
00281 OTV_Validator valid )
00282 {
00283 FT_Bytes p = table;
00284 FT_UInt SubstFormat;
00285
00286
00287 OTV_NAME_ENTER( "ContextSubst" );
00288
00289 OTV_LIMIT_CHECK( 2 );
00290 SubstFormat = FT_NEXT_USHORT( p );
00291
00292 OTV_TRACE(( " (format %d)\n", SubstFormat ));
00293
00294 switch ( SubstFormat )
00295 {
00296 case 1:
00297
00298
00299
00300
00301 valid->extra1 = valid->lookup_count;
00302 OTV_NEST3( ContextSubstFormat1, SubRuleSet, SubRule );
00303 OTV_RUN( table, valid );
00304 break;
00305
00306 case 2:
00307
00308
00309
00310
00311 OTV_NEST3( ContextSubstFormat2, SubClassSet, SubClassRule );
00312 OTV_RUN( table, valid );
00313 break;
00314
00315 case 3:
00316 OTV_NEST1( ContextSubstFormat3 );
00317 OTV_RUN( table, valid );
00318 break;
00319
00320 default:
00321 FT_INVALID_FORMAT;
00322 }
00323
00324 OTV_EXIT;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 static void
00339 otv_ChainContextSubst_validate( FT_Bytes table,
00340 OTV_Validator valid )
00341 {
00342 FT_Bytes p = table;
00343 FT_UInt SubstFormat;
00344
00345
00346 OTV_NAME_ENTER( "ChainContextSubst" );
00347
00348 OTV_LIMIT_CHECK( 2 );
00349 SubstFormat = FT_NEXT_USHORT( p );
00350
00351 OTV_TRACE(( " (format %d)\n", SubstFormat ));
00352
00353 switch ( SubstFormat )
00354 {
00355 case 1:
00356
00357
00358
00359
00360 valid->extra1 = valid->lookup_count;
00361 OTV_NEST3( ChainContextSubstFormat1,
00362 ChainSubRuleSet, ChainSubRule );
00363 OTV_RUN( table, valid );
00364 break;
00365
00366 case 2:
00367
00368
00369
00370
00371 OTV_NEST3( ChainContextSubstFormat2,
00372 ChainSubClassSet, ChainSubClassRule );
00373 OTV_RUN( table, valid );
00374 break;
00375
00376 case 3:
00377 OTV_NEST1( ChainContextSubstFormat3 );
00378 OTV_RUN( table, valid );
00379 break;
00380
00381 default:
00382 FT_INVALID_FORMAT;
00383 }
00384
00385 OTV_EXIT;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 static void
00400 otv_ExtensionSubst_validate( FT_Bytes table,
00401 OTV_Validator valid )
00402 {
00403 FT_Bytes p = table;
00404 FT_UInt SubstFormat;
00405
00406
00407 OTV_NAME_ENTER( "ExtensionSubst" );
00408
00409 OTV_LIMIT_CHECK( 2 );
00410 SubstFormat = FT_NEXT_USHORT( p );
00411
00412 OTV_TRACE(( " (format %d)\n", SubstFormat ));
00413
00414 switch ( SubstFormat )
00415 {
00416 case 1:
00417 {
00418 FT_UInt ExtensionLookupType;
00419 FT_ULong ExtensionOffset;
00420 OTV_Validate_Func validate;
00421
00422
00423 OTV_LIMIT_CHECK( 6 );
00424 ExtensionLookupType = FT_NEXT_USHORT( p );
00425 ExtensionOffset = FT_NEXT_ULONG( p );
00426
00427 if ( ExtensionLookupType == 0 ||
00428 ExtensionLookupType == 7 ||
00429 ExtensionLookupType > 8 )
00430 FT_INVALID_DATA;
00431
00432 validate = valid->type_funcs[ExtensionLookupType - 1];
00433 validate( table + ExtensionOffset, valid );
00434 }
00435 break;
00436
00437 default:
00438 FT_INVALID_FORMAT;
00439 }
00440
00441 OTV_EXIT;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 static void
00456 otv_ReverseChainSingleSubst_validate( FT_Bytes table,
00457 OTV_Validator valid )
00458 {
00459 FT_Bytes p = table, Coverage;
00460 FT_UInt SubstFormat;
00461 FT_UInt BacktrackGlyphCount, LookaheadGlyphCount, GlyphCount;
00462
00463
00464 OTV_NAME_ENTER( "ReverseChainSingleSubst" );
00465
00466 OTV_LIMIT_CHECK( 2 );
00467 SubstFormat = FT_NEXT_USHORT( p );
00468
00469 OTV_TRACE(( " (format %d)\n", SubstFormat ));
00470
00471 switch ( SubstFormat )
00472 {
00473 case 1:
00474 OTV_LIMIT_CHECK( 4 );
00475 Coverage = table + FT_NEXT_USHORT( p );
00476 BacktrackGlyphCount = FT_NEXT_USHORT( p );
00477
00478 OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
00479
00480 otv_Coverage_validate( Coverage, valid, -1 );
00481
00482 OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
00483
00484 for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
00485 otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
00486
00487 LookaheadGlyphCount = FT_NEXT_USHORT( p );
00488
00489 OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
00490
00491 OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
00492
00493 for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
00494 otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
00495
00496 GlyphCount = FT_NEXT_USHORT( p );
00497
00498 OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
00499
00500 if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
00501 FT_INVALID_DATA;
00502
00503 OTV_LIMIT_CHECK( GlyphCount * 2 );
00504
00505
00506 for ( ; GlyphCount > 0; GlyphCount-- )
00507 if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
00508 FT_INVALID_DATA;
00509
00510 break;
00511
00512 default:
00513 FT_INVALID_FORMAT;
00514 }
00515
00516 OTV_EXIT;
00517 }
00518
00519
00520 static const OTV_Validate_Func otv_gsub_validate_funcs[8] =
00521 {
00522 otv_SingleSubst_validate,
00523 otv_MultipleSubst_validate,
00524 otv_AlternateSubst_validate,
00525 otv_LigatureSubst_validate,
00526 otv_ContextSubst_validate,
00527 otv_ChainContextSubst_validate,
00528 otv_ExtensionSubst_validate,
00529 otv_ReverseChainSingleSubst_validate
00530 };
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 FT_LOCAL_DEF( void )
00546 otv_GSUB_validate( FT_Bytes table,
00547 FT_UInt glyph_count,
00548 FT_Validator ftvalid )
00549 {
00550 OTV_ValidatorRec validrec;
00551 OTV_Validator valid = &validrec;
00552 FT_Bytes p = table;
00553 FT_UInt ScriptList, FeatureList, LookupList;
00554
00555
00556 valid->root = ftvalid;
00557
00558 FT_TRACE3(( "validating GSUB table\n" ));
00559 OTV_INIT;
00560
00561 OTV_LIMIT_CHECK( 10 );
00562
00563 if ( FT_NEXT_ULONG( p ) != 0x10000UL )
00564 FT_INVALID_FORMAT;
00565
00566 ScriptList = FT_NEXT_USHORT( p );
00567 FeatureList = FT_NEXT_USHORT( p );
00568 LookupList = FT_NEXT_USHORT( p );
00569
00570 valid->type_count = 8;
00571 valid->type_funcs = (OTV_Validate_Func*)otv_gsub_validate_funcs;
00572 valid->glyph_count = glyph_count;
00573
00574 otv_LookupList_validate( table + LookupList,
00575 valid );
00576 otv_FeatureList_validate( table + FeatureList, table + LookupList,
00577 valid );
00578 otv_ScriptList_validate( table + ScriptList, table + FeatureList,
00579 valid );
00580
00581 FT_TRACE4(( "\n" ));
00582 }
00583
00584
00585