(root)/
freetype-2.13.2/
src/
otvalid/
otvcommn.c
       1  /****************************************************************************
       2   *
       3   * otvcommn.c
       4   *
       5   *   OpenType common tables validation (body).
       6   *
       7   * Copyright (C) 2004-2023 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 %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      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 %d)\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 = %d)\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 = %d)\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 %d)\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 = %d)\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 = %d)\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 = %d)\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 = %d)\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 = %d)\n", ReqFeatureIndex ));
     536      OTV_TRACE(( " (FeatureCount = %d)\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 = %d)\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 = %d)\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 = %d)\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 = %d)\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 = %d)\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 = %d)\n", Count1 ));
     769      OTV_TRACE(( " (Count2 = %d)\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 = %d)\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 = %d)\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 = %d)\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 = %d)\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 = %d)\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 = %d)\n", GlyphCount ));
     914      OTV_TRACE(( " (Count = %d)\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 = %d)\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 = %d)\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 = %d)\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 = %d)\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 = %d)\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 */