tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

otvcommn.c (27533B)


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