Home | History | Annotate | Download | only in otvalid
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  otvcommn.c                                                             */
      4 /*                                                                         */
      5 /*    OpenType common tables validation (body).                            */
      6 /*                                                                         */
      7 /*  Copyright 2004-2018 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 "otvcommn.h"
     20 
     21 
     22   /*************************************************************************/
     23   /*                                                                       */
     24   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     25   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     26   /* messages during execution.                                            */
     27   /*                                                                       */
     28 #undef  FT_COMPONENT
     29 #define FT_COMPONENT  trace_otvcommon
     30 
     31 
     32   /*************************************************************************/
     33   /*************************************************************************/
     34   /*****                                                               *****/
     35   /*****                       COVERAGE TABLE                          *****/
     36   /*****                                                               *****/
     37   /*************************************************************************/
     38   /*************************************************************************/
     39 
     40   FT_LOCAL_DEF( void )
     41   otv_Coverage_validate( FT_Bytes       table,
     42                          OTV_Validator  otvalid,
     43                          FT_Int         expected_count )
     44   {
     45     FT_Bytes  p = table;
     46     FT_UInt   CoverageFormat;
     47     FT_UInt   total = 0;
     48 
     49 
     50     OTV_NAME_ENTER( "Coverage" );
     51 
     52     OTV_LIMIT_CHECK( 4 );
     53     CoverageFormat = FT_NEXT_USHORT( p );
     54 
     55     OTV_TRACE(( " (format %d)\n", CoverageFormat ));
     56 
     57     switch ( CoverageFormat )
     58     {
     59     case 1:     /* CoverageFormat1 */
     60       {
     61         FT_UInt  GlyphCount;
     62         FT_UInt  i;
     63 
     64 
     65         GlyphCount = FT_NEXT_USHORT( p );
     66 
     67         OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
     68 
     69         OTV_LIMIT_CHECK( GlyphCount * 2 );        /* GlyphArray */
     70 
     71         for ( i = 0; i < GlyphCount; i++ )
     72         {
     73           FT_UInt  gid;
     74 
     75 
     76           gid = FT_NEXT_USHORT( p );
     77           if ( gid >= otvalid->glyph_count )
     78             FT_INVALID_GLYPH_ID;
     79         }
     80 
     81         total = GlyphCount;
     82       }
     83       break;
     84 
     85     case 2:     /* CoverageFormat2 */
     86       {
     87         FT_UInt  n, RangeCount;
     88         FT_UInt  Start, End, StartCoverageIndex, last = 0;
     89 
     90 
     91         RangeCount = FT_NEXT_USHORT( p );
     92 
     93         OTV_TRACE(( " (RangeCount = %d)\n", RangeCount ));
     94 
     95         OTV_LIMIT_CHECK( RangeCount * 6 );
     96 
     97         /* RangeRecord */
     98         for ( n = 0; n < RangeCount; n++ )
     99         {
    100           Start              = FT_NEXT_USHORT( p );
    101           End                = FT_NEXT_USHORT( p );
    102           StartCoverageIndex = FT_NEXT_USHORT( p );
    103 
    104           if ( Start > End || StartCoverageIndex != total )
    105             FT_INVALID_DATA;
    106 
    107           if ( End >= otvalid->glyph_count )
    108             FT_INVALID_GLYPH_ID;
    109 
    110           if ( n > 0 && Start <= last )
    111             FT_INVALID_DATA;
    112 
    113           total += End - Start + 1;
    114           last   = End;
    115         }
    116       }
    117       break;
    118 
    119     default:
    120       FT_INVALID_FORMAT;
    121     }
    122 
    123     /* Generally, a coverage table offset has an associated count field.  */
    124     /* The number of glyphs in the table should match this field.  If     */
    125     /* there is no associated count, a value of -1 tells us not to check. */
    126     if ( expected_count != -1 && (FT_UInt)expected_count != total )
    127       FT_INVALID_DATA;
    128 
    129     OTV_EXIT;
    130   }
    131 
    132 
    133   FT_LOCAL_DEF( FT_UInt )
    134   otv_Coverage_get_first( FT_Bytes  table )
    135   {
    136     FT_Bytes  p = table;
    137 
    138 
    139     p += 4;     /* skip CoverageFormat and Glyph/RangeCount */
    140 
    141     return FT_NEXT_USHORT( p );
    142   }
    143 
    144 
    145   FT_LOCAL_DEF( FT_UInt )
    146   otv_Coverage_get_last( FT_Bytes  table )
    147   {
    148     FT_Bytes  p = table;
    149     FT_UInt   CoverageFormat = FT_NEXT_USHORT( p );
    150     FT_UInt   count          = FT_NEXT_USHORT( p );     /* Glyph/RangeCount */
    151     FT_UInt   result = 0;
    152 
    153 
    154     switch ( CoverageFormat )
    155     {
    156     case 1:
    157       p += ( count - 1 ) * 2;
    158       result = FT_NEXT_USHORT( p );
    159       break;
    160 
    161     case 2:
    162       p += ( count - 1 ) * 6 + 2;
    163       result = FT_NEXT_USHORT( p );
    164       break;
    165 
    166     default:
    167       ;
    168     }
    169 
    170     return result;
    171   }
    172 
    173 
    174   FT_LOCAL_DEF( FT_UInt )
    175   otv_Coverage_get_count( FT_Bytes  table )
    176   {
    177     FT_Bytes  p              = table;
    178     FT_UInt   CoverageFormat = FT_NEXT_USHORT( p );
    179     FT_UInt   count          = FT_NEXT_USHORT( p );     /* Glyph/RangeCount */
    180     FT_UInt   result         = 0;
    181 
    182 
    183     switch ( CoverageFormat )
    184     {
    185     case 1:
    186       return count;
    187 
    188     case 2:
    189       {
    190         FT_UInt  Start, End;
    191 
    192 
    193         for ( ; count > 0; count-- )
    194         {
    195           Start = FT_NEXT_USHORT( p );
    196           End   = FT_NEXT_USHORT( p );
    197           p    += 2;                    /* skip StartCoverageIndex */
    198 
    199           result += End - Start + 1;
    200         }
    201       }
    202       break;
    203 
    204     default:
    205       ;
    206     }
    207 
    208     return result;
    209   }
    210 
    211 
    212   /*************************************************************************/
    213   /*************************************************************************/
    214   /*****                                                               *****/
    215   /*****                   CLASS DEFINITION TABLE                      *****/
    216   /*****                                                               *****/
    217   /*************************************************************************/
    218   /*************************************************************************/
    219 
    220   FT_LOCAL_DEF( void )
    221   otv_ClassDef_validate( FT_Bytes       table,
    222                          OTV_Validator  otvalid )
    223   {
    224     FT_Bytes  p = table;
    225     FT_UInt   ClassFormat;
    226 
    227 
    228     OTV_NAME_ENTER( "ClassDef" );
    229 
    230     OTV_LIMIT_CHECK( 4 );
    231     ClassFormat = FT_NEXT_USHORT( p );
    232 
    233     OTV_TRACE(( " (format %d)\n", ClassFormat ));
    234 
    235     switch ( ClassFormat )
    236     {
    237     case 1:     /* ClassDefFormat1 */
    238       {
    239         FT_UInt  StartGlyph;
    240         FT_UInt  GlyphCount;
    241 
    242 
    243         OTV_LIMIT_CHECK( 4 );
    244 
    245         StartGlyph = FT_NEXT_USHORT( p );
    246         GlyphCount = FT_NEXT_USHORT( p );
    247 
    248         OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
    249 
    250         OTV_LIMIT_CHECK( GlyphCount * 2 );    /* ClassValueArray */
    251 
    252         if ( StartGlyph + GlyphCount - 1 >= otvalid->glyph_count )
    253           FT_INVALID_GLYPH_ID;
    254       }
    255       break;
    256 
    257     case 2:     /* ClassDefFormat2 */
    258       {
    259         FT_UInt  n, ClassRangeCount;
    260         FT_UInt  Start, End, last = 0;
    261 
    262 
    263         ClassRangeCount = FT_NEXT_USHORT( p );
    264 
    265         OTV_TRACE(( " (ClassRangeCount = %d)\n", ClassRangeCount ));
    266 
    267         OTV_LIMIT_CHECK( ClassRangeCount * 6 );
    268 
    269         /* ClassRangeRecord */
    270         for ( n = 0; n < ClassRangeCount; n++ )
    271         {
    272           Start = FT_NEXT_USHORT( p );
    273           End   = FT_NEXT_USHORT( p );
    274           p    += 2;                        /* skip Class */
    275 
    276           if ( Start > End || ( n > 0 && Start <= last ) )
    277             FT_INVALID_DATA;
    278 
    279           if ( End >= otvalid->glyph_count )
    280             FT_INVALID_GLYPH_ID;
    281 
    282           last = End;
    283         }
    284       }
    285       break;
    286 
    287     default:
    288       FT_INVALID_FORMAT;
    289     }
    290 
    291     /* no need to check glyph indices used as input to class definition   */
    292     /* tables since even invalid glyph indices return a meaningful result */
    293 
    294     OTV_EXIT;
    295   }
    296 
    297 
    298   /*************************************************************************/
    299   /*************************************************************************/
    300   /*****                                                               *****/
    301   /*****                      DEVICE TABLE                             *****/
    302   /*****                                                               *****/
    303   /*************************************************************************/
    304   /*************************************************************************/
    305 
    306   FT_LOCAL_DEF( void )
    307   otv_Device_validate( FT_Bytes       table,
    308                        OTV_Validator  otvalid )
    309   {
    310     FT_Bytes  p = table;
    311     FT_UInt   StartSize, EndSize, DeltaFormat, count;
    312 
    313 
    314     OTV_NAME_ENTER( "Device" );
    315 
    316     OTV_LIMIT_CHECK( 6 );
    317     StartSize   = FT_NEXT_USHORT( p );
    318     EndSize     = FT_NEXT_USHORT( p );
    319     DeltaFormat = FT_NEXT_USHORT( p );
    320 
    321     if ( DeltaFormat == 0x8000U )
    322     {
    323       /* VariationIndex, nothing to do */
    324     }
    325     else
    326     {
    327       if ( DeltaFormat < 1 || DeltaFormat > 3 )
    328         FT_INVALID_FORMAT;
    329 
    330       if ( EndSize < StartSize )
    331         FT_INVALID_DATA;
    332 
    333       count = EndSize - StartSize + 1;
    334       OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 );  /* DeltaValue */
    335     }
    336 
    337     OTV_EXIT;
    338   }
    339 
    340 
    341   /*************************************************************************/
    342   /*************************************************************************/
    343   /*****                                                               *****/
    344   /*****                         LOOKUPS                               *****/
    345   /*****                                                               *****/
    346   /*************************************************************************/
    347   /*************************************************************************/
    348 
    349   /* uses otvalid->type_count */
    350   /* uses otvalid->type_funcs */
    351 
    352   FT_LOCAL_DEF( void )
    353   otv_Lookup_validate( FT_Bytes       table,
    354                        OTV_Validator  otvalid )
    355   {
    356     FT_Bytes           p = table;
    357     FT_UInt            LookupType, LookupFlag, SubTableCount;
    358     OTV_Validate_Func  validate;
    359 
    360 
    361     OTV_NAME_ENTER( "Lookup" );
    362 
    363     OTV_LIMIT_CHECK( 6 );
    364     LookupType    = FT_NEXT_USHORT( p );
    365     LookupFlag    = FT_NEXT_USHORT( p );
    366     SubTableCount = FT_NEXT_USHORT( p );
    367 
    368     OTV_TRACE(( " (type %d)\n", LookupType ));
    369 
    370     if ( LookupType == 0 || LookupType > otvalid->type_count )
    371       FT_INVALID_DATA;
    372 
    373     validate = otvalid->type_funcs[LookupType - 1];
    374 
    375     OTV_TRACE(( " (SubTableCount = %d)\n", SubTableCount ));
    376 
    377     OTV_LIMIT_CHECK( SubTableCount * 2 );
    378 
    379     /* SubTable */
    380     for ( ; SubTableCount > 0; SubTableCount-- )
    381       validate( table + FT_NEXT_USHORT( p ), otvalid );
    382 
    383     if ( LookupFlag & 0x10 )
    384       OTV_LIMIT_CHECK( 2 );  /* MarkFilteringSet */
    385 
    386     OTV_EXIT;
    387   }
    388 
    389 
    390   /* uses valid->lookup_count */
    391 
    392   FT_LOCAL_DEF( void )
    393   otv_LookupList_validate( FT_Bytes       table,
    394                            OTV_Validator  otvalid )
    395   {
    396     FT_Bytes  p = table;
    397     FT_UInt   LookupCount;
    398 
    399 
    400     OTV_NAME_ENTER( "LookupList" );
    401 
    402     OTV_LIMIT_CHECK( 2 );
    403     LookupCount = FT_NEXT_USHORT( p );
    404 
    405     OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
    406 
    407     OTV_LIMIT_CHECK( LookupCount * 2 );
    408 
    409     otvalid->lookup_count = LookupCount;
    410 
    411     /* Lookup */
    412     for ( ; LookupCount > 0; LookupCount-- )
    413       otv_Lookup_validate( table + FT_NEXT_USHORT( p ), otvalid );
    414 
    415     OTV_EXIT;
    416   }
    417 
    418 
    419   static FT_UInt
    420   otv_LookupList_get_count( FT_Bytes  table )
    421   {
    422     return FT_NEXT_USHORT( table );
    423   }
    424 
    425 
    426   /*************************************************************************/
    427   /*************************************************************************/
    428   /*****                                                               *****/
    429   /*****                        FEATURES                               *****/
    430   /*****                                                               *****/
    431   /*************************************************************************/
    432   /*************************************************************************/
    433 
    434   /* uses otvalid->lookup_count */
    435 
    436   FT_LOCAL_DEF( void )
    437   otv_Feature_validate( FT_Bytes       table,
    438                         OTV_Validator  otvalid )
    439   {
    440     FT_Bytes  p = table;
    441     FT_UInt   LookupCount;
    442 
    443 
    444     OTV_NAME_ENTER( "Feature" );
    445 
    446     OTV_LIMIT_CHECK( 4 );
    447     p           += 2;                   /* skip FeatureParams (unused) */
    448     LookupCount  = FT_NEXT_USHORT( p );
    449 
    450     OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
    451 
    452     OTV_LIMIT_CHECK( LookupCount * 2 );
    453 
    454     /* LookupListIndex */
    455     for ( ; LookupCount > 0; LookupCount-- )
    456       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
    457         FT_INVALID_DATA;
    458 
    459     OTV_EXIT;
    460   }
    461 
    462 
    463   static FT_UInt
    464   otv_Feature_get_count( FT_Bytes  table )
    465   {
    466     return FT_NEXT_USHORT( table );
    467   }
    468 
    469 
    470   /* sets otvalid->lookup_count */
    471 
    472   FT_LOCAL_DEF( void )
    473   otv_FeatureList_validate( FT_Bytes       table,
    474                             FT_Bytes       lookups,
    475                             OTV_Validator  otvalid )
    476   {
    477     FT_Bytes  p = table;
    478     FT_UInt   FeatureCount;
    479 
    480 
    481     OTV_NAME_ENTER( "FeatureList" );
    482 
    483     OTV_LIMIT_CHECK( 2 );
    484     FeatureCount = FT_NEXT_USHORT( p );
    485 
    486     OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount ));
    487 
    488     OTV_LIMIT_CHECK( FeatureCount * 2 );
    489 
    490     otvalid->lookup_count = otv_LookupList_get_count( lookups );
    491 
    492     /* FeatureRecord */
    493     for ( ; FeatureCount > 0; FeatureCount-- )
    494     {
    495       p += 4;       /* skip FeatureTag */
    496 
    497       /* Feature */
    498       otv_Feature_validate( table + FT_NEXT_USHORT( p ), otvalid );
    499     }
    500 
    501     OTV_EXIT;
    502   }
    503 
    504 
    505   /*************************************************************************/
    506   /*************************************************************************/
    507   /*****                                                               *****/
    508   /*****                       LANGUAGE SYSTEM                         *****/
    509   /*****                                                               *****/
    510   /*************************************************************************/
    511   /*************************************************************************/
    512 
    513 
    514   /* uses otvalid->extra1 (number of features) */
    515 
    516   FT_LOCAL_DEF( void )
    517   otv_LangSys_validate( FT_Bytes       table,
    518                         OTV_Validator  otvalid )
    519   {
    520     FT_Bytes  p = table;
    521     FT_UInt   ReqFeatureIndex;
    522     FT_UInt   FeatureCount;
    523 
    524 
    525     OTV_NAME_ENTER( "LangSys" );
    526 
    527     OTV_LIMIT_CHECK( 6 );
    528     p              += 2;                    /* skip LookupOrder (unused) */
    529     ReqFeatureIndex = FT_NEXT_USHORT( p );
    530     FeatureCount    = FT_NEXT_USHORT( p );
    531 
    532     OTV_TRACE(( " (ReqFeatureIndex = %d)\n", ReqFeatureIndex ));
    533     OTV_TRACE(( " (FeatureCount = %d)\n",    FeatureCount    ));
    534 
    535     if ( ReqFeatureIndex != 0xFFFFU && ReqFeatureIndex >= otvalid->extra1 )
    536       FT_INVALID_DATA;
    537 
    538     OTV_LIMIT_CHECK( FeatureCount * 2 );
    539 
    540     /* FeatureIndex */
    541     for ( ; FeatureCount > 0; FeatureCount-- )
    542       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
    543         FT_INVALID_DATA;
    544 
    545     OTV_EXIT;
    546   }
    547 
    548 
    549   /*************************************************************************/
    550   /*************************************************************************/
    551   /*****                                                               *****/
    552   /*****                           SCRIPTS                             *****/
    553   /*****                                                               *****/
    554   /*************************************************************************/
    555   /*************************************************************************/
    556 
    557   FT_LOCAL_DEF( void )
    558   otv_Script_validate( FT_Bytes       table,
    559                        OTV_Validator  otvalid )
    560   {
    561     FT_UInt   DefaultLangSys, LangSysCount;
    562     FT_Bytes  p = table;
    563 
    564 
    565     OTV_NAME_ENTER( "Script" );
    566 
    567     OTV_LIMIT_CHECK( 4 );
    568     DefaultLangSys = FT_NEXT_USHORT( p );
    569     LangSysCount   = FT_NEXT_USHORT( p );
    570 
    571     OTV_TRACE(( " (LangSysCount = %d)\n", LangSysCount ));
    572 
    573     if ( DefaultLangSys != 0 )
    574       otv_LangSys_validate( table + DefaultLangSys, otvalid );
    575 
    576     OTV_LIMIT_CHECK( LangSysCount * 6 );
    577 
    578     /* LangSysRecord */
    579     for ( ; LangSysCount > 0; LangSysCount-- )
    580     {
    581       p += 4;       /* skip LangSysTag */
    582 
    583       /* LangSys */
    584       otv_LangSys_validate( table + FT_NEXT_USHORT( p ), otvalid );
    585     }
    586 
    587     OTV_EXIT;
    588   }
    589 
    590 
    591   /* sets otvalid->extra1 (number of features) */
    592 
    593   FT_LOCAL_DEF( void )
    594   otv_ScriptList_validate( FT_Bytes       table,
    595                            FT_Bytes       features,
    596                            OTV_Validator  otvalid )
    597   {
    598     FT_UInt   ScriptCount;
    599     FT_Bytes  p = table;
    600 
    601 
    602     OTV_NAME_ENTER( "ScriptList" );
    603 
    604     OTV_LIMIT_CHECK( 2 );
    605     ScriptCount = FT_NEXT_USHORT( p );
    606 
    607     OTV_TRACE(( " (ScriptCount = %d)\n", ScriptCount ));
    608 
    609     OTV_LIMIT_CHECK( ScriptCount * 6 );
    610 
    611     otvalid->extra1 = otv_Feature_get_count( features );
    612 
    613     /* ScriptRecord */
    614     for ( ; ScriptCount > 0; ScriptCount-- )
    615     {
    616       p += 4;       /* skip ScriptTag */
    617 
    618       otv_Script_validate( table + FT_NEXT_USHORT( p ), otvalid ); /* Script */
    619     }
    620 
    621     OTV_EXIT;
    622   }
    623 
    624 
    625   /*************************************************************************/
    626   /*************************************************************************/
    627   /*****                                                               *****/
    628   /*****                      UTILITY FUNCTIONS                        *****/
    629   /*****                                                               *****/
    630   /*************************************************************************/
    631   /*************************************************************************/
    632 
    633   /*
    634      u:   uint16
    635      ux:  unit16 [x]
    636 
    637      s:   struct
    638      sx:  struct [x]
    639      sxy: struct [x], using external y count
    640 
    641      x:   uint16 x
    642 
    643      C:   Coverage
    644 
    645      O:   Offset
    646      On:  Offset (NULL)
    647      Ox:  Offset [x]
    648      Onx: Offset (NULL) [x]
    649   */
    650 
    651   FT_LOCAL_DEF( void )
    652   otv_x_Ox( FT_Bytes       table,
    653             OTV_Validator  otvalid )
    654   {
    655     FT_Bytes           p = table;
    656     FT_UInt            Count;
    657     OTV_Validate_Func  func;
    658 
    659 
    660     OTV_ENTER;
    661 
    662     OTV_LIMIT_CHECK( 2 );
    663     Count = FT_NEXT_USHORT( p );
    664 
    665     OTV_TRACE(( " (Count = %d)\n", Count ));
    666 
    667     OTV_LIMIT_CHECK( Count * 2 );
    668 
    669     otvalid->nesting_level++;
    670     func = otvalid->func[otvalid->nesting_level];
    671 
    672     for ( ; Count > 0; Count-- )
    673       func( table + FT_NEXT_USHORT( p ), otvalid );
    674 
    675     otvalid->nesting_level--;
    676 
    677     OTV_EXIT;
    678   }
    679 
    680 
    681   FT_LOCAL_DEF( void )
    682   otv_u_C_x_Ox( FT_Bytes       table,
    683                 OTV_Validator  otvalid )
    684   {
    685     FT_Bytes           p = table;
    686     FT_UInt            Count, Coverage;
    687     OTV_Validate_Func  func;
    688 
    689 
    690     OTV_ENTER;
    691 
    692     p += 2;     /* skip Format */
    693 
    694     OTV_LIMIT_CHECK( 4 );
    695     Coverage = FT_NEXT_USHORT( p );
    696     Count    = FT_NEXT_USHORT( p );
    697 
    698     OTV_TRACE(( " (Count = %d)\n", Count ));
    699 
    700     otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)Count );
    701 
    702     OTV_LIMIT_CHECK( Count * 2 );
    703 
    704     otvalid->nesting_level++;
    705     func = otvalid->func[otvalid->nesting_level];
    706 
    707     for ( ; Count > 0; Count-- )
    708       func( table + FT_NEXT_USHORT( p ), otvalid );
    709 
    710     otvalid->nesting_level--;
    711 
    712     OTV_EXIT;
    713   }
    714 
    715 
    716   /* uses otvalid->extra1 (if > 0: array value limit) */
    717 
    718   FT_LOCAL_DEF( void )
    719   otv_x_ux( FT_Bytes       table,
    720             OTV_Validator  otvalid )
    721   {
    722     FT_Bytes  p = table;
    723     FT_UInt   Count;
    724 
    725 
    726     OTV_ENTER;
    727 
    728     OTV_LIMIT_CHECK( 2 );
    729     Count = FT_NEXT_USHORT( p );
    730 
    731     OTV_TRACE(( " (Count = %d)\n", Count ));
    732 
    733     OTV_LIMIT_CHECK( Count * 2 );
    734 
    735     if ( otvalid->extra1 )
    736     {
    737       for ( ; Count > 0; Count-- )
    738         if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
    739           FT_INVALID_DATA;
    740     }
    741 
    742     OTV_EXIT;
    743   }
    744 
    745 
    746   /* `ux' in the function's name is not really correct since only x-1 */
    747   /* elements are tested                                              */
    748 
    749   /* uses otvalid->extra1 (array value limit) */
    750 
    751   FT_LOCAL_DEF( void )
    752   otv_x_y_ux_sy( FT_Bytes       table,
    753                  OTV_Validator  otvalid )
    754   {
    755     FT_Bytes  p = table;
    756     FT_UInt   Count1, Count2;
    757 
    758 
    759     OTV_ENTER;
    760 
    761     OTV_LIMIT_CHECK( 4 );
    762     Count1 = FT_NEXT_USHORT( p );
    763     Count2 = FT_NEXT_USHORT( p );
    764 
    765     OTV_TRACE(( " (Count1 = %d)\n", Count1 ));
    766     OTV_TRACE(( " (Count2 = %d)\n", Count2 ));
    767 
    768     if ( Count1 == 0 )
    769       FT_INVALID_DATA;
    770 
    771     OTV_LIMIT_CHECK( ( Count1 - 1 ) * 2 + Count2 * 4 );
    772     p += ( Count1 - 1 ) * 2;
    773 
    774     for ( ; Count2 > 0; Count2-- )
    775     {
    776       if ( FT_NEXT_USHORT( p ) >= Count1 )
    777         FT_INVALID_DATA;
    778 
    779       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
    780         FT_INVALID_DATA;
    781     }
    782 
    783     OTV_EXIT;
    784   }
    785 
    786 
    787   /* `uy' in the function's name is not really correct since only y-1 */
    788   /* elements are tested                                              */
    789 
    790   /* uses otvalid->extra1 (array value limit) */
    791 
    792   FT_LOCAL_DEF( void )
    793   otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes       table,
    794                            OTV_Validator  otvalid )
    795   {
    796     FT_Bytes  p = table;
    797     FT_UInt   BacktrackCount, InputCount, LookaheadCount;
    798     FT_UInt   Count;
    799 
    800 
    801     OTV_ENTER;
    802 
    803     OTV_LIMIT_CHECK( 2 );
    804     BacktrackCount = FT_NEXT_USHORT( p );
    805 
    806     OTV_TRACE(( " (BacktrackCount = %d)\n", BacktrackCount ));
    807 
    808     OTV_LIMIT_CHECK( BacktrackCount * 2 + 2 );
    809     p += BacktrackCount * 2;
    810 
    811     InputCount = FT_NEXT_USHORT( p );
    812     if ( InputCount == 0 )
    813       FT_INVALID_DATA;
    814 
    815     OTV_TRACE(( " (InputCount = %d)\n", InputCount ));
    816 
    817     OTV_LIMIT_CHECK( InputCount * 2 );
    818     p += ( InputCount - 1 ) * 2;
    819 
    820     LookaheadCount = FT_NEXT_USHORT( p );
    821 
    822     OTV_TRACE(( " (LookaheadCount = %d)\n", LookaheadCount ));
    823 
    824     OTV_LIMIT_CHECK( LookaheadCount * 2 + 2 );
    825     p += LookaheadCount * 2;
    826 
    827     Count = FT_NEXT_USHORT( p );
    828 
    829     OTV_TRACE(( " (Count = %d)\n", Count ));
    830 
    831     OTV_LIMIT_CHECK( Count * 4 );
    832 
    833     for ( ; Count > 0; Count-- )
    834     {
    835       if ( FT_NEXT_USHORT( p ) >= InputCount )
    836         FT_INVALID_DATA;
    837 
    838       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
    839         FT_INVALID_DATA;
    840     }
    841 
    842     OTV_EXIT;
    843   }
    844 
    845 
    846   /* sets otvalid->extra1 (valid->lookup_count) */
    847 
    848   FT_LOCAL_DEF( void )
    849   otv_u_O_O_x_Onx( FT_Bytes       table,
    850                    OTV_Validator  otvalid )
    851   {
    852     FT_Bytes           p = table;
    853     FT_UInt            Coverage, ClassDef, ClassSetCount;
    854     OTV_Validate_Func  func;
    855 
    856 
    857     OTV_ENTER;
    858 
    859     p += 2;     /* skip Format */
    860 
    861     OTV_LIMIT_CHECK( 6 );
    862     Coverage      = FT_NEXT_USHORT( p );
    863     ClassDef      = FT_NEXT_USHORT( p );
    864     ClassSetCount = FT_NEXT_USHORT( p );
    865 
    866     OTV_TRACE(( " (ClassSetCount = %d)\n", ClassSetCount ));
    867 
    868     otv_Coverage_validate( table + Coverage, otvalid, -1 );
    869     otv_ClassDef_validate( table + ClassDef, otvalid );
    870 
    871     OTV_LIMIT_CHECK( ClassSetCount * 2 );
    872 
    873     otvalid->nesting_level++;
    874     func          = otvalid->func[otvalid->nesting_level];
    875     otvalid->extra1 = otvalid->lookup_count;
    876 
    877     for ( ; ClassSetCount > 0; ClassSetCount-- )
    878     {
    879       FT_UInt  offset = FT_NEXT_USHORT( p );
    880 
    881 
    882       if ( offset )
    883         func( table + offset, otvalid );
    884     }
    885 
    886     otvalid->nesting_level--;
    887 
    888     OTV_EXIT;
    889   }
    890 
    891 
    892   /* uses otvalid->lookup_count */
    893 
    894   FT_LOCAL_DEF( void )
    895   otv_u_x_y_Ox_sy( FT_Bytes       table,
    896                    OTV_Validator  otvalid )
    897   {
    898     FT_Bytes  p = table;
    899     FT_UInt   GlyphCount, Count, count1;
    900 
    901 
    902     OTV_ENTER;
    903 
    904     p += 2;     /* skip Format */
    905 
    906     OTV_LIMIT_CHECK( 4 );
    907     GlyphCount = FT_NEXT_USHORT( p );
    908     Count      = FT_NEXT_USHORT( p );
    909 
    910     OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
    911     OTV_TRACE(( " (Count = %d)\n",      Count      ));
    912 
    913     OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 );
    914 
    915     for ( count1 = GlyphCount; count1 > 0; count1-- )
    916       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
    917 
    918     for ( ; Count > 0; Count-- )
    919     {
    920       if ( FT_NEXT_USHORT( p ) >= GlyphCount )
    921         FT_INVALID_DATA;
    922 
    923       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
    924         FT_INVALID_DATA;
    925     }
    926 
    927     OTV_EXIT;
    928   }
    929 
    930 
    931   /* sets otvalid->extra1 (valid->lookup_count)    */
    932 
    933   FT_LOCAL_DEF( void )
    934   otv_u_O_O_O_O_x_Onx( FT_Bytes       table,
    935                        OTV_Validator  otvalid )
    936   {
    937     FT_Bytes           p = table;
    938     FT_UInt            Coverage;
    939     FT_UInt            BacktrackClassDef, InputClassDef, LookaheadClassDef;
    940     FT_UInt            ChainClassSetCount;
    941     OTV_Validate_Func  func;
    942 
    943 
    944     OTV_ENTER;
    945 
    946     p += 2;     /* skip Format */
    947 
    948     OTV_LIMIT_CHECK( 10 );
    949     Coverage           = FT_NEXT_USHORT( p );
    950     BacktrackClassDef  = FT_NEXT_USHORT( p );
    951     InputClassDef      = FT_NEXT_USHORT( p );
    952     LookaheadClassDef  = FT_NEXT_USHORT( p );
    953     ChainClassSetCount = FT_NEXT_USHORT( p );
    954 
    955     OTV_TRACE(( " (ChainClassSetCount = %d)\n", ChainClassSetCount ));
    956 
    957     otv_Coverage_validate( table + Coverage, otvalid, -1 );
    958 
    959     otv_ClassDef_validate( table + BacktrackClassDef,  otvalid );
    960     otv_ClassDef_validate( table + InputClassDef, otvalid );
    961     otv_ClassDef_validate( table + LookaheadClassDef, otvalid );
    962 
    963     OTV_LIMIT_CHECK( ChainClassSetCount * 2 );
    964 
    965     otvalid->nesting_level++;
    966     func          = otvalid->func[otvalid->nesting_level];
    967     otvalid->extra1 = otvalid->lookup_count;
    968 
    969     for ( ; ChainClassSetCount > 0; ChainClassSetCount-- )
    970     {
    971       FT_UInt  offset = FT_NEXT_USHORT( p );
    972 
    973 
    974       if ( offset )
    975         func( table + offset, otvalid );
    976     }
    977 
    978     otvalid->nesting_level--;
    979 
    980     OTV_EXIT;
    981   }
    982 
    983 
    984   /* uses otvalid->lookup_count */
    985 
    986   FT_LOCAL_DEF( void )
    987   otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes       table,
    988                              OTV_Validator  otvalid )
    989   {
    990     FT_Bytes  p = table;
    991     FT_UInt   BacktrackGlyphCount, InputGlyphCount, LookaheadGlyphCount;
    992     FT_UInt   count1, count2;
    993 
    994 
    995     OTV_ENTER;
    996 
    997     p += 2;     /* skip Format */
    998 
    999     OTV_LIMIT_CHECK( 2 );
   1000     BacktrackGlyphCount = FT_NEXT_USHORT( p );
   1001 
   1002     OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
   1003 
   1004     OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
   1005 
   1006     for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
   1007       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
   1008 
   1009     InputGlyphCount = FT_NEXT_USHORT( p );
   1010 
   1011     OTV_TRACE(( " (InputGlyphCount = %d)\n", InputGlyphCount ));
   1012 
   1013     OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 );
   1014 
   1015     for ( count1 = InputGlyphCount; count1 > 0; count1-- )
   1016       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
   1017 
   1018     LookaheadGlyphCount = FT_NEXT_USHORT( p );
   1019 
   1020     OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
   1021 
   1022     OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
   1023 
   1024     for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
   1025       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
   1026 
   1027     count2 = FT_NEXT_USHORT( p );
   1028 
   1029     OTV_TRACE(( " (Count = %d)\n", count2 ));
   1030 
   1031     OTV_LIMIT_CHECK( count2 * 4 );
   1032 
   1033     for ( ; count2 > 0; count2-- )
   1034     {
   1035       if ( FT_NEXT_USHORT( p ) >= InputGlyphCount )
   1036         FT_INVALID_DATA;
   1037 
   1038       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
   1039         FT_INVALID_DATA;
   1040     }
   1041 
   1042     OTV_EXIT;
   1043   }
   1044 
   1045 
   1046   FT_LOCAL_DEF( FT_UInt )
   1047   otv_GSUBGPOS_get_Lookup_count( FT_Bytes  table )
   1048   {
   1049     FT_Bytes  p = table + 8;
   1050 
   1051 
   1052     return otv_LookupList_get_count( table + FT_NEXT_USHORT( p ) );
   1053   }
   1054 
   1055 
   1056   FT_LOCAL_DEF( FT_UInt )
   1057   otv_GSUBGPOS_have_MarkAttachmentType_flag( FT_Bytes  table )
   1058   {
   1059     FT_Bytes  p, lookup;
   1060     FT_UInt   count;
   1061 
   1062 
   1063     if ( !table )
   1064       return 0;
   1065 
   1066     /* LookupList */
   1067     p      = table + 8;
   1068     table += FT_NEXT_USHORT( p );
   1069 
   1070     /* LookupCount */
   1071     p     = table;
   1072     count = FT_NEXT_USHORT( p );
   1073 
   1074     for ( ; count > 0; count-- )
   1075     {
   1076       FT_Bytes  oldp;
   1077 
   1078 
   1079       /* Lookup */
   1080       lookup = table + FT_NEXT_USHORT( p );
   1081 
   1082       oldp = p;
   1083 
   1084       /* LookupFlag */
   1085       p = lookup + 2;
   1086       if ( FT_NEXT_USHORT( p ) & 0xFF00U )
   1087         return 1;
   1088 
   1089       p = oldp;
   1090     }
   1091 
   1092     return 0;
   1093   }
   1094 
   1095 
   1096 /* END */
   1097