PageRenderTime 58ms CodeModel.GetById 13ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/src/freetype/src/otvalid/otvcommn.c

https://bitbucket.org/cabalistic/ogredeps/
C | 1086 lines | 613 code | 339 blank | 134 comment | 76 complexity | 81979eae8db8a538ab47fc2c98d2d83c MD5 | raw file
   1/***************************************************************************/
   2/*                                                                         */
   3/*  otvcommn.c                                                             */
   4/*                                                                         */
   5/*    OpenType common tables validation (body).                            */
   6/*                                                                         */
   7/*  Copyright 2004, 2005, 2006, 2007 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  valid,
  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 >= valid->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 >= valid->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  valid )
 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 >= valid->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 >= valid->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  valid )
 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 valid->type_count */
 343  /* uses valid->type_funcs */
 344
 345  FT_LOCAL_DEF( void )
 346  otv_Lookup_validate( FT_Bytes       table,
 347                       OTV_Validator  valid )
 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 > valid->type_count )
 364      FT_INVALID_DATA;
 365
 366    validate = valid->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 ), valid );
 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  valid )
 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    valid->lookup_count = LookupCount;
 400
 401    /* Lookup */
 402    for ( ; LookupCount > 0; LookupCount-- )
 403      otv_Lookup_validate( table + FT_NEXT_USHORT( p ), valid );
 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 valid->lookup_count */
 425
 426  FT_LOCAL_DEF( void )
 427  otv_Feature_validate( FT_Bytes       table,
 428                        OTV_Validator  valid )
 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 ) >= valid->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 valid->lookup_count */
 461
 462  FT_LOCAL_DEF( void )
 463  otv_FeatureList_validate( FT_Bytes       table,
 464                            FT_Bytes       lookups,
 465                            OTV_Validator  valid )
 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    valid->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 ), valid );
 489    }
 490
 491    OTV_EXIT;
 492  }
 493
 494
 495  /*************************************************************************/
 496  /*************************************************************************/
 497  /*****                                                               *****/
 498  /*****                       LANGUAGE SYSTEM                         *****/
 499  /*****                                                               *****/
 500  /*************************************************************************/
 501  /*************************************************************************/
 502
 503
 504  /* uses valid->extra1 (number of features) */
 505
 506  FT_LOCAL_DEF( void )
 507  otv_LangSys_validate( FT_Bytes       table,
 508                        OTV_Validator  valid )
 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 >= valid->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 ) >= valid->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  valid )
 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, valid );
 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 ), valid );
 575    }
 576
 577    OTV_EXIT;
 578  }
 579
 580
 581  /* sets valid->extra1 (number of features) */
 582
 583  FT_LOCAL_DEF( void )
 584  otv_ScriptList_validate( FT_Bytes       table,
 585                           FT_Bytes       features,
 586                           OTV_Validator  valid )
 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    valid->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 ), valid ); /* 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  valid )
 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    valid->nesting_level++;
 660    func = valid->func[valid->nesting_level];
 661
 662    for ( ; Count > 0; Count-- )
 663      func( table + FT_NEXT_USHORT( p ), valid );
 664
 665    valid->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  valid )
 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, valid, Count );
 691
 692    OTV_LIMIT_CHECK( Count * 2 );
 693
 694    valid->nesting_level++;
 695    func = valid->func[valid->nesting_level];
 696
 697    for ( ; Count > 0; Count-- )
 698      func( table + FT_NEXT_USHORT( p ), valid );
 699
 700    valid->nesting_level--;
 701
 702    OTV_EXIT;
 703  }
 704
 705
 706  /* uses valid->extra1 (if > 0: array value limit) */
 707
 708  FT_LOCAL_DEF( void )
 709  otv_x_ux( FT_Bytes       table,
 710            OTV_Validator  valid )
 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 ( valid->extra1 )
 726    {
 727      for ( ; Count > 0; Count-- )
 728        if ( FT_NEXT_USHORT( p ) >= valid->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 valid->extra1 (array value limit) */
 740
 741  FT_LOCAL_DEF( void )
 742  otv_x_y_ux_sy( FT_Bytes       table,
 743                 OTV_Validator  valid )
 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 ) >= valid->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 valid->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  valid )
 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 ) >= valid->extra1 )
 829        FT_INVALID_DATA;
 830    }
 831
 832    OTV_EXIT;
 833  }
 834
 835
 836  /* sets valid->extra1 (valid->lookup_count) */
 837
 838  FT_LOCAL_DEF( void )
 839  otv_u_O_O_x_Onx( FT_Bytes       table,
 840                   OTV_Validator  valid )
 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, valid, -1 );
 859    otv_ClassDef_validate( table + ClassDef, valid );
 860
 861    OTV_LIMIT_CHECK( ClassSetCount * 2 );
 862
 863    valid->nesting_level++;
 864    func          = valid->func[valid->nesting_level];
 865    valid->extra1 = valid->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, valid );
 874    }
 875
 876    valid->nesting_level--;
 877
 878    OTV_EXIT;
 879  }
 880
 881
 882  /* uses valid->lookup_count */
 883
 884  FT_LOCAL_DEF( void )
 885  otv_u_x_y_Ox_sy( FT_Bytes       table,
 886                   OTV_Validator  valid )
 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 ), valid, -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 ) >= valid->lookup_count )
 914        FT_INVALID_DATA;
 915    }
 916
 917    OTV_EXIT;
 918  }
 919
 920
 921  /* sets valid->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  valid )
 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, valid, -1 );
 948
 949    otv_ClassDef_validate( table + BacktrackClassDef,  valid );
 950    otv_ClassDef_validate( table + InputClassDef, valid );
 951    otv_ClassDef_validate( table + LookaheadClassDef, valid );
 952
 953    OTV_LIMIT_CHECK( ChainClassSetCount * 2 );
 954
 955    valid->nesting_level++;
 956    func          = valid->func[valid->nesting_level];
 957    valid->extra1 = valid->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, valid );
 966    }
 967
 968    valid->nesting_level--;
 969
 970    OTV_EXIT;
 971  }
 972
 973
 974  /* uses valid->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  valid )
 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 ), valid, -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 ), valid, -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 ), valid, -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 ) >= valid->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 */