Home | History | Annotate | Download | only in otvalid
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  otvcommn.c                                                             */
      4 /*                                                                         */
      5 /*    OpenType common tables validation (body).                            */
      6 /*                                                                         */
      7 /*  Copyright 2004-2015 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( 8 );
    317     StartSize   = FT_NEXT_USHORT( p );
    318     EndSize     = FT_NEXT_USHORT( p );
    319     DeltaFormat = FT_NEXT_USHORT( p );
    320 
    321     if ( DeltaFormat < 1 || DeltaFormat > 3 )
    322       FT_INVALID_FORMAT;
    323 
    324     if ( EndSize < StartSize )
    325       FT_INVALID_DATA;
    326 
    327     count = EndSize - StartSize + 1;
    328     OTV_LIMIT_CHECK( ( 1 << DeltaFormat ) * count / 8 );  /* DeltaValue */
    329 
    330     OTV_EXIT;
    331   }
    332 
    333 
    334   /*************************************************************************/
    335   /*************************************************************************/
    336   /*****                                                               *****/
    337   /*****                         LOOKUPS                               *****/
    338   /*****                                                               *****/
    339   /*************************************************************************/
    340   /*************************************************************************/
    341 
    342   /* uses otvalid->type_count */
    343   /* uses otvalid->type_funcs */
    344 
    345   FT_LOCAL_DEF( void )
    346   otv_Lookup_validate( FT_Bytes       table,
    347                        OTV_Validator  otvalid )
    348   {
    349     FT_Bytes           p = table;
    350     FT_UInt            LookupType, SubTableCount;
    351     OTV_Validate_Func  validate;
    352 
    353 
    354     OTV_NAME_ENTER( "Lookup" );
    355 
    356     OTV_LIMIT_CHECK( 6 );
    357     LookupType    = FT_NEXT_USHORT( p );
    358     p            += 2;                      /* skip LookupFlag */
    359     SubTableCount = FT_NEXT_USHORT( p );
    360 
    361     OTV_TRACE(( " (type %d)\n", LookupType ));
    362 
    363     if ( LookupType == 0 || LookupType > otvalid->type_count )
    364       FT_INVALID_DATA;
    365 
    366     validate = otvalid->type_funcs[LookupType - 1];
    367 
    368     OTV_TRACE(( " (SubTableCount = %d)\n", SubTableCount ));
    369 
    370     OTV_LIMIT_CHECK( SubTableCount * 2 );
    371 
    372     /* SubTable */
    373     for ( ; SubTableCount > 0; SubTableCount-- )
    374       validate( table + FT_NEXT_USHORT( p ), otvalid );
    375 
    376     OTV_EXIT;
    377   }
    378 
    379 
    380   /* uses valid->lookup_count */
    381 
    382   FT_LOCAL_DEF( void )
    383   otv_LookupList_validate( FT_Bytes       table,
    384                            OTV_Validator  otvalid )
    385   {
    386     FT_Bytes  p = table;
    387     FT_UInt   LookupCount;
    388 
    389 
    390     OTV_NAME_ENTER( "LookupList" );
    391 
    392     OTV_LIMIT_CHECK( 2 );
    393     LookupCount = FT_NEXT_USHORT( p );
    394 
    395     OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
    396 
    397     OTV_LIMIT_CHECK( LookupCount * 2 );
    398 
    399     otvalid->lookup_count = LookupCount;
    400 
    401     /* Lookup */
    402     for ( ; LookupCount > 0; LookupCount-- )
    403       otv_Lookup_validate( table + FT_NEXT_USHORT( p ), otvalid );
    404 
    405     OTV_EXIT;
    406   }
    407 
    408 
    409   static FT_UInt
    410   otv_LookupList_get_count( FT_Bytes  table )
    411   {
    412     return FT_NEXT_USHORT( table );
    413   }
    414 
    415 
    416   /*************************************************************************/
    417   /*************************************************************************/
    418   /*****                                                               *****/
    419   /*****                        FEATURES                               *****/
    420   /*****                                                               *****/
    421   /*************************************************************************/
    422   /*************************************************************************/
    423 
    424   /* uses otvalid->lookup_count */
    425 
    426   FT_LOCAL_DEF( void )
    427   otv_Feature_validate( FT_Bytes       table,
    428                         OTV_Validator  otvalid )
    429   {
    430     FT_Bytes  p = table;
    431     FT_UInt   LookupCount;
    432 
    433 
    434     OTV_NAME_ENTER( "Feature" );
    435 
    436     OTV_LIMIT_CHECK( 4 );
    437     p           += 2;                   /* skip FeatureParams (unused) */
    438     LookupCount  = FT_NEXT_USHORT( p );
    439 
    440     OTV_TRACE(( " (LookupCount = %d)\n", LookupCount ));
    441 
    442     OTV_LIMIT_CHECK( LookupCount * 2 );
    443 
    444     /* LookupListIndex */
    445     for ( ; LookupCount > 0; LookupCount-- )
    446       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
    447         FT_INVALID_DATA;
    448 
    449     OTV_EXIT;
    450   }
    451 
    452 
    453   static FT_UInt
    454   otv_Feature_get_count( FT_Bytes  table )
    455   {
    456     return FT_NEXT_USHORT( table );
    457   }
    458 
    459 
    460   /* sets otvalid->lookup_count */
    461 
    462   FT_LOCAL_DEF( void )
    463   otv_FeatureList_validate( FT_Bytes       table,
    464                             FT_Bytes       lookups,
    465                             OTV_Validator  otvalid )
    466   {
    467     FT_Bytes  p = table;
    468     FT_UInt   FeatureCount;
    469 
    470 
    471     OTV_NAME_ENTER( "FeatureList" );
    472 
    473     OTV_LIMIT_CHECK( 2 );
    474     FeatureCount = FT_NEXT_USHORT( p );
    475 
    476     OTV_TRACE(( " (FeatureCount = %d)\n", FeatureCount ));
    477 
    478     OTV_LIMIT_CHECK( FeatureCount * 2 );
    479 
    480     otvalid->lookup_count = otv_LookupList_get_count( lookups );
    481 
    482     /* FeatureRecord */
    483     for ( ; FeatureCount > 0; FeatureCount-- )
    484     {
    485       p += 4;       /* skip FeatureTag */
    486 
    487       /* Feature */
    488       otv_Feature_validate( table + FT_NEXT_USHORT( p ), otvalid );
    489     }
    490 
    491     OTV_EXIT;
    492   }
    493 
    494 
    495   /*************************************************************************/
    496   /*************************************************************************/
    497   /*****                                                               *****/
    498   /*****                       LANGUAGE SYSTEM                         *****/
    499   /*****                                                               *****/
    500   /*************************************************************************/
    501   /*************************************************************************/
    502 
    503 
    504   /* uses otvalid->extra1 (number of features) */
    505 
    506   FT_LOCAL_DEF( void )
    507   otv_LangSys_validate( FT_Bytes       table,
    508                         OTV_Validator  otvalid )
    509   {
    510     FT_Bytes  p = table;
    511     FT_UInt   ReqFeatureIndex;
    512     FT_UInt   FeatureCount;
    513 
    514 
    515     OTV_NAME_ENTER( "LangSys" );
    516 
    517     OTV_LIMIT_CHECK( 6 );
    518     p              += 2;                    /* skip LookupOrder (unused) */
    519     ReqFeatureIndex = FT_NEXT_USHORT( p );
    520     FeatureCount    = FT_NEXT_USHORT( p );
    521 
    522     OTV_TRACE(( " (ReqFeatureIndex = %d)\n", ReqFeatureIndex ));
    523     OTV_TRACE(( " (FeatureCount = %d)\n",    FeatureCount    ));
    524 
    525     if ( ReqFeatureIndex != 0xFFFFU && ReqFeatureIndex >= otvalid->extra1 )
    526       FT_INVALID_DATA;
    527 
    528     OTV_LIMIT_CHECK( FeatureCount * 2 );
    529 
    530     /* FeatureIndex */
    531     for ( ; FeatureCount > 0; FeatureCount-- )
    532       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
    533         FT_INVALID_DATA;
    534 
    535     OTV_EXIT;
    536   }
    537 
    538 
    539   /*************************************************************************/
    540   /*************************************************************************/
    541   /*****                                                               *****/
    542   /*****                           SCRIPTS                             *****/
    543   /*****                                                               *****/
    544   /*************************************************************************/
    545   /*************************************************************************/
    546 
    547   FT_LOCAL_DEF( void )
    548   otv_Script_validate( FT_Bytes       table,
    549                        OTV_Validator  otvalid )
    550   {
    551     FT_UInt   DefaultLangSys, LangSysCount;
    552     FT_Bytes  p = table;
    553 
    554 
    555     OTV_NAME_ENTER( "Script" );
    556 
    557     OTV_LIMIT_CHECK( 4 );
    558     DefaultLangSys = FT_NEXT_USHORT( p );
    559     LangSysCount   = FT_NEXT_USHORT( p );
    560 
    561     OTV_TRACE(( " (LangSysCount = %d)\n", LangSysCount ));
    562 
    563     if ( DefaultLangSys != 0 )
    564       otv_LangSys_validate( table + DefaultLangSys, otvalid );
    565 
    566     OTV_LIMIT_CHECK( LangSysCount * 6 );
    567 
    568     /* LangSysRecord */
    569     for ( ; LangSysCount > 0; LangSysCount-- )
    570     {
    571       p += 4;       /* skip LangSysTag */
    572 
    573       /* LangSys */
    574       otv_LangSys_validate( table + FT_NEXT_USHORT( p ), otvalid );
    575     }
    576 
    577     OTV_EXIT;
    578   }
    579 
    580 
    581   /* sets otvalid->extra1 (number of features) */
    582 
    583   FT_LOCAL_DEF( void )
    584   otv_ScriptList_validate( FT_Bytes       table,
    585                            FT_Bytes       features,
    586                            OTV_Validator  otvalid )
    587   {
    588     FT_UInt   ScriptCount;
    589     FT_Bytes  p = table;
    590 
    591 
    592     OTV_NAME_ENTER( "ScriptList" );
    593 
    594     OTV_LIMIT_CHECK( 2 );
    595     ScriptCount = FT_NEXT_USHORT( p );
    596 
    597     OTV_TRACE(( " (ScriptCount = %d)\n", ScriptCount ));
    598 
    599     OTV_LIMIT_CHECK( ScriptCount * 6 );
    600 
    601     otvalid->extra1 = otv_Feature_get_count( features );
    602 
    603     /* ScriptRecord */
    604     for ( ; ScriptCount > 0; ScriptCount-- )
    605     {
    606       p += 4;       /* skip ScriptTag */
    607 
    608       otv_Script_validate( table + FT_NEXT_USHORT( p ), otvalid ); /* Script */
    609     }
    610 
    611     OTV_EXIT;
    612   }
    613 
    614 
    615   /*************************************************************************/
    616   /*************************************************************************/
    617   /*****                                                               *****/
    618   /*****                      UTILITY FUNCTIONS                        *****/
    619   /*****                                                               *****/
    620   /*************************************************************************/
    621   /*************************************************************************/
    622 
    623   /*
    624      u:   uint16
    625      ux:  unit16 [x]
    626 
    627      s:   struct
    628      sx:  struct [x]
    629      sxy: struct [x], using external y count
    630 
    631      x:   uint16 x
    632 
    633      C:   Coverage
    634 
    635      O:   Offset
    636      On:  Offset (NULL)
    637      Ox:  Offset [x]
    638      Onx: Offset (NULL) [x]
    639   */
    640 
    641   FT_LOCAL_DEF( void )
    642   otv_x_Ox( FT_Bytes       table,
    643             OTV_Validator  otvalid )
    644   {
    645     FT_Bytes           p = table;
    646     FT_UInt            Count;
    647     OTV_Validate_Func  func;
    648 
    649 
    650     OTV_ENTER;
    651 
    652     OTV_LIMIT_CHECK( 2 );
    653     Count = FT_NEXT_USHORT( p );
    654 
    655     OTV_TRACE(( " (Count = %d)\n", Count ));
    656 
    657     OTV_LIMIT_CHECK( Count * 2 );
    658 
    659     otvalid->nesting_level++;
    660     func = otvalid->func[otvalid->nesting_level];
    661 
    662     for ( ; Count > 0; Count-- )
    663       func( table + FT_NEXT_USHORT( p ), otvalid );
    664 
    665     otvalid->nesting_level--;
    666 
    667     OTV_EXIT;
    668   }
    669 
    670 
    671   FT_LOCAL_DEF( void )
    672   otv_u_C_x_Ox( FT_Bytes       table,
    673                 OTV_Validator  otvalid )
    674   {
    675     FT_Bytes           p = table;
    676     FT_UInt            Count, Coverage;
    677     OTV_Validate_Func  func;
    678 
    679 
    680     OTV_ENTER;
    681 
    682     p += 2;     /* skip Format */
    683 
    684     OTV_LIMIT_CHECK( 4 );
    685     Coverage = FT_NEXT_USHORT( p );
    686     Count    = FT_NEXT_USHORT( p );
    687 
    688     OTV_TRACE(( " (Count = %d)\n", Count ));
    689 
    690     otv_Coverage_validate( table + Coverage, otvalid, (FT_Int)Count );
    691 
    692     OTV_LIMIT_CHECK( Count * 2 );
    693 
    694     otvalid->nesting_level++;
    695     func = otvalid->func[otvalid->nesting_level];
    696 
    697     for ( ; Count > 0; Count-- )
    698       func( table + FT_NEXT_USHORT( p ), otvalid );
    699 
    700     otvalid->nesting_level--;
    701 
    702     OTV_EXIT;
    703   }
    704 
    705 
    706   /* uses otvalid->extra1 (if > 0: array value limit) */
    707 
    708   FT_LOCAL_DEF( void )
    709   otv_x_ux( FT_Bytes       table,
    710             OTV_Validator  otvalid )
    711   {
    712     FT_Bytes  p = table;
    713     FT_UInt   Count;
    714 
    715 
    716     OTV_ENTER;
    717 
    718     OTV_LIMIT_CHECK( 2 );
    719     Count = FT_NEXT_USHORT( p );
    720 
    721     OTV_TRACE(( " (Count = %d)\n", Count ));
    722 
    723     OTV_LIMIT_CHECK( Count * 2 );
    724 
    725     if ( otvalid->extra1 )
    726     {
    727       for ( ; Count > 0; Count-- )
    728         if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
    729           FT_INVALID_DATA;
    730     }
    731 
    732     OTV_EXIT;
    733   }
    734 
    735 
    736   /* `ux' in the function's name is not really correct since only x-1 */
    737   /* elements are tested                                              */
    738 
    739   /* uses otvalid->extra1 (array value limit) */
    740 
    741   FT_LOCAL_DEF( void )
    742   otv_x_y_ux_sy( FT_Bytes       table,
    743                  OTV_Validator  otvalid )
    744   {
    745     FT_Bytes  p = table;
    746     FT_UInt   Count1, Count2;
    747 
    748 
    749     OTV_ENTER;
    750 
    751     OTV_LIMIT_CHECK( 4 );
    752     Count1 = FT_NEXT_USHORT( p );
    753     Count2 = FT_NEXT_USHORT( p );
    754 
    755     OTV_TRACE(( " (Count1 = %d)\n", Count1 ));
    756     OTV_TRACE(( " (Count2 = %d)\n", Count2 ));
    757 
    758     if ( Count1 == 0 )
    759       FT_INVALID_DATA;
    760 
    761     OTV_LIMIT_CHECK( ( Count1 - 1 ) * 2 + Count2 * 4 );
    762     p += ( Count1 - 1 ) * 2;
    763 
    764     for ( ; Count2 > 0; Count2-- )
    765     {
    766       if ( FT_NEXT_USHORT( p ) >= Count1 )
    767         FT_INVALID_DATA;
    768 
    769       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
    770         FT_INVALID_DATA;
    771     }
    772 
    773     OTV_EXIT;
    774   }
    775 
    776 
    777   /* `uy' in the function's name is not really correct since only y-1 */
    778   /* elements are tested                                              */
    779 
    780   /* uses otvalid->extra1 (array value limit) */
    781 
    782   FT_LOCAL_DEF( void )
    783   otv_x_ux_y_uy_z_uz_p_sp( FT_Bytes       table,
    784                            OTV_Validator  otvalid )
    785   {
    786     FT_Bytes  p = table;
    787     FT_UInt   BacktrackCount, InputCount, LookaheadCount;
    788     FT_UInt   Count;
    789 
    790 
    791     OTV_ENTER;
    792 
    793     OTV_LIMIT_CHECK( 2 );
    794     BacktrackCount = FT_NEXT_USHORT( p );
    795 
    796     OTV_TRACE(( " (BacktrackCount = %d)\n", BacktrackCount ));
    797 
    798     OTV_LIMIT_CHECK( BacktrackCount * 2 + 2 );
    799     p += BacktrackCount * 2;
    800 
    801     InputCount = FT_NEXT_USHORT( p );
    802     if ( InputCount == 0 )
    803       FT_INVALID_DATA;
    804 
    805     OTV_TRACE(( " (InputCount = %d)\n", InputCount ));
    806 
    807     OTV_LIMIT_CHECK( InputCount * 2 );
    808     p += ( InputCount - 1 ) * 2;
    809 
    810     LookaheadCount = FT_NEXT_USHORT( p );
    811 
    812     OTV_TRACE(( " (LookaheadCount = %d)\n", LookaheadCount ));
    813 
    814     OTV_LIMIT_CHECK( LookaheadCount * 2 + 2 );
    815     p += LookaheadCount * 2;
    816 
    817     Count = FT_NEXT_USHORT( p );
    818 
    819     OTV_TRACE(( " (Count = %d)\n", Count ));
    820 
    821     OTV_LIMIT_CHECK( Count * 4 );
    822 
    823     for ( ; Count > 0; Count-- )
    824     {
    825       if ( FT_NEXT_USHORT( p ) >= InputCount )
    826         FT_INVALID_DATA;
    827 
    828       if ( FT_NEXT_USHORT( p ) >= otvalid->extra1 )
    829         FT_INVALID_DATA;
    830     }
    831 
    832     OTV_EXIT;
    833   }
    834 
    835 
    836   /* sets otvalid->extra1 (valid->lookup_count) */
    837 
    838   FT_LOCAL_DEF( void )
    839   otv_u_O_O_x_Onx( FT_Bytes       table,
    840                    OTV_Validator  otvalid )
    841   {
    842     FT_Bytes           p = table;
    843     FT_UInt            Coverage, ClassDef, ClassSetCount;
    844     OTV_Validate_Func  func;
    845 
    846 
    847     OTV_ENTER;
    848 
    849     p += 2;     /* skip Format */
    850 
    851     OTV_LIMIT_CHECK( 6 );
    852     Coverage      = FT_NEXT_USHORT( p );
    853     ClassDef      = FT_NEXT_USHORT( p );
    854     ClassSetCount = FT_NEXT_USHORT( p );
    855 
    856     OTV_TRACE(( " (ClassSetCount = %d)\n", ClassSetCount ));
    857 
    858     otv_Coverage_validate( table + Coverage, otvalid, -1 );
    859     otv_ClassDef_validate( table + ClassDef, otvalid );
    860 
    861     OTV_LIMIT_CHECK( ClassSetCount * 2 );
    862 
    863     otvalid->nesting_level++;
    864     func          = otvalid->func[otvalid->nesting_level];
    865     otvalid->extra1 = otvalid->lookup_count;
    866 
    867     for ( ; ClassSetCount > 0; ClassSetCount-- )
    868     {
    869       FT_UInt  offset = FT_NEXT_USHORT( p );
    870 
    871 
    872       if ( offset )
    873         func( table + offset, otvalid );
    874     }
    875 
    876     otvalid->nesting_level--;
    877 
    878     OTV_EXIT;
    879   }
    880 
    881 
    882   /* uses otvalid->lookup_count */
    883 
    884   FT_LOCAL_DEF( void )
    885   otv_u_x_y_Ox_sy( FT_Bytes       table,
    886                    OTV_Validator  otvalid )
    887   {
    888     FT_Bytes  p = table;
    889     FT_UInt   GlyphCount, Count, count1;
    890 
    891 
    892     OTV_ENTER;
    893 
    894     p += 2;     /* skip Format */
    895 
    896     OTV_LIMIT_CHECK( 4 );
    897     GlyphCount = FT_NEXT_USHORT( p );
    898     Count      = FT_NEXT_USHORT( p );
    899 
    900     OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
    901     OTV_TRACE(( " (Count = %d)\n",      Count      ));
    902 
    903     OTV_LIMIT_CHECK( GlyphCount * 2 + Count * 4 );
    904 
    905     for ( count1 = GlyphCount; count1 > 0; count1-- )
    906       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
    907 
    908     for ( ; Count > 0; Count-- )
    909     {
    910       if ( FT_NEXT_USHORT( p ) >= GlyphCount )
    911         FT_INVALID_DATA;
    912 
    913       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
    914         FT_INVALID_DATA;
    915     }
    916 
    917     OTV_EXIT;
    918   }
    919 
    920 
    921   /* sets otvalid->extra1 (valid->lookup_count)    */
    922 
    923   FT_LOCAL_DEF( void )
    924   otv_u_O_O_O_O_x_Onx( FT_Bytes       table,
    925                        OTV_Validator  otvalid )
    926   {
    927     FT_Bytes           p = table;
    928     FT_UInt            Coverage;
    929     FT_UInt            BacktrackClassDef, InputClassDef, LookaheadClassDef;
    930     FT_UInt            ChainClassSetCount;
    931     OTV_Validate_Func  func;
    932 
    933 
    934     OTV_ENTER;
    935 
    936     p += 2;     /* skip Format */
    937 
    938     OTV_LIMIT_CHECK( 10 );
    939     Coverage           = FT_NEXT_USHORT( p );
    940     BacktrackClassDef  = FT_NEXT_USHORT( p );
    941     InputClassDef      = FT_NEXT_USHORT( p );
    942     LookaheadClassDef  = FT_NEXT_USHORT( p );
    943     ChainClassSetCount = FT_NEXT_USHORT( p );
    944 
    945     OTV_TRACE(( " (ChainClassSetCount = %d)\n", ChainClassSetCount ));
    946 
    947     otv_Coverage_validate( table + Coverage, otvalid, -1 );
    948 
    949     otv_ClassDef_validate( table + BacktrackClassDef,  otvalid );
    950     otv_ClassDef_validate( table + InputClassDef, otvalid );
    951     otv_ClassDef_validate( table + LookaheadClassDef, otvalid );
    952 
    953     OTV_LIMIT_CHECK( ChainClassSetCount * 2 );
    954 
    955     otvalid->nesting_level++;
    956     func          = otvalid->func[otvalid->nesting_level];
    957     otvalid->extra1 = otvalid->lookup_count;
    958 
    959     for ( ; ChainClassSetCount > 0; ChainClassSetCount-- )
    960     {
    961       FT_UInt  offset = FT_NEXT_USHORT( p );
    962 
    963 
    964       if ( offset )
    965         func( table + offset, otvalid );
    966     }
    967 
    968     otvalid->nesting_level--;
    969 
    970     OTV_EXIT;
    971   }
    972 
    973 
    974   /* uses otvalid->lookup_count */
    975 
    976   FT_LOCAL_DEF( void )
    977   otv_u_x_Ox_y_Oy_z_Oz_p_sp( FT_Bytes       table,
    978                              OTV_Validator  otvalid )
    979   {
    980     FT_Bytes  p = table;
    981     FT_UInt   BacktrackGlyphCount, InputGlyphCount, LookaheadGlyphCount;
    982     FT_UInt   count1, count2;
    983 
    984 
    985     OTV_ENTER;
    986 
    987     p += 2;     /* skip Format */
    988 
    989     OTV_LIMIT_CHECK( 2 );
    990     BacktrackGlyphCount = FT_NEXT_USHORT( p );
    991 
    992     OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
    993 
    994     OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
    995 
    996     for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
    997       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
    998 
    999     InputGlyphCount = FT_NEXT_USHORT( p );
   1000 
   1001     OTV_TRACE(( " (InputGlyphCount = %d)\n", InputGlyphCount ));
   1002 
   1003     OTV_LIMIT_CHECK( InputGlyphCount * 2 + 2 );
   1004 
   1005     for ( count1 = InputGlyphCount; count1 > 0; count1-- )
   1006       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
   1007 
   1008     LookaheadGlyphCount = FT_NEXT_USHORT( p );
   1009 
   1010     OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
   1011 
   1012     OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
   1013 
   1014     for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
   1015       otv_Coverage_validate( table + FT_NEXT_USHORT( p ), otvalid, -1 );
   1016 
   1017     count2 = FT_NEXT_USHORT( p );
   1018 
   1019     OTV_TRACE(( " (Count = %d)\n", count2 ));
   1020 
   1021     OTV_LIMIT_CHECK( count2 * 4 );
   1022 
   1023     for ( ; count2 > 0; count2-- )
   1024     {
   1025       if ( FT_NEXT_USHORT( p ) >= InputGlyphCount )
   1026         FT_INVALID_DATA;
   1027 
   1028       if ( FT_NEXT_USHORT( p ) >= otvalid->lookup_count )
   1029         FT_INVALID_DATA;
   1030     }
   1031 
   1032     OTV_EXIT;
   1033   }
   1034 
   1035 
   1036   FT_LOCAL_DEF( FT_UInt )
   1037   otv_GSUBGPOS_get_Lookup_count( FT_Bytes  table )
   1038   {
   1039     FT_Bytes  p = table + 8;
   1040 
   1041 
   1042     return otv_LookupList_get_count( table + FT_NEXT_USHORT( p ) );
   1043   }
   1044 
   1045 
   1046   FT_LOCAL_DEF( FT_UInt )
   1047   otv_GSUBGPOS_have_MarkAttachmentType_flag( FT_Bytes  table )
   1048   {
   1049     FT_Bytes  p, lookup;
   1050     FT_UInt   count;
   1051 
   1052 
   1053     if ( !table )
   1054       return 0;
   1055 
   1056     /* LookupList */
   1057     p      = table + 8;
   1058     table += FT_NEXT_USHORT( p );
   1059 
   1060     /* LookupCount */
   1061     p     = table;
   1062     count = FT_NEXT_USHORT( p );
   1063 
   1064     for ( ; count > 0; count-- )
   1065     {
   1066       FT_Bytes  oldp;
   1067 
   1068 
   1069       /* Lookup */
   1070       lookup = table + FT_NEXT_USHORT( p );
   1071 
   1072       oldp = p;
   1073 
   1074       /* LookupFlag */
   1075       p = lookup + 2;
   1076       if ( FT_NEXT_USHORT( p ) & 0xFF00U )
   1077         return 1;
   1078 
   1079       p = oldp;
   1080     }
   1081 
   1082     return 0;
   1083   }
   1084 
   1085 
   1086 /* END */
   1087