freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Git][freetype/freetype][master] [truetype] Keep variation store consist


From: Werner Lemberg (@wl)
Subject: [Git][freetype/freetype][master] [truetype] Keep variation store consistent.
Date: Fri, 06 Jan 2023 06:23:17 +0000

Werner Lemberg pushed to branch master at FreeType / FreeType

Commits:

  • 262b47ac
    by Ben Wagner at 2023-01-06T07:11:41+01:00
    [truetype] Keep variation store consistent.
    
    `tt_var_load_item_variation_store` fills out a `GX_ItemVarStore`.  While it
    may return an error, the item store must be left in a consistent state so
    that any use or destruction of the item store can properly use or free the
    data in it.  Before this change the counts from the font data were read
    directly into the item store before the actual allocation of the arrays to
    which they referred.  There exist many opportunities between the time the
    counts are read and the arrays are allocated to return early due to invalid
    data.  When this happened the item store claimed to have entires it actually
    did not, leading to crashes later when it was used.
    
    Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=54449
    
    * src/truetype/ttgxvar.c (tt_var_load_item_variation_store): Read the counts
    into local variables and store them in the item store only after the related
    arrays are actually created on the item store.
    

1 changed file:

Changes:

  • src/truetype/ttgxvar.c
    ... ... @@ -502,13 +502,15 @@
    502 502
         FT_Error   error;
    
    503 503
         FT_UShort  format;
    
    504 504
         FT_ULong   region_offset;
    
    505
    -    FT_UInt    i, j, k;
    
    506
    -    FT_UInt    wordDeltaCount;
    
    507
    -    FT_Bool    long_words;
    
    508 505
     
    
    509
    -    GX_Blend        blend = face->blend;
    
    510
    -    GX_ItemVarData  varData;
    
    506
    +    FT_UInt    data_count;
    
    507
    +    FT_UShort  axis_count;
    
    508
    +    FT_UInt    region_count;
    
    511 509
     
    
    510
    +    FT_UInt  i, j, k;
    
    511
    +    FT_Bool  long_words;
    
    512
    +
    
    513
    +    GX_Blend   blend           = face->blend;
    
    512 514
         FT_ULong*  dataOffsetArray = NULL;
    
    513 515
     
    
    514 516
     
    
    ... ... @@ -525,12 +527,12 @@
    525 527
         }
    
    526 528
     
    
    527 529
         /* read top level fields */
    
    528
    -    if ( FT_READ_ULONG( region_offset )         ||
    
    529
    -         FT_READ_USHORT( itemStore->dataCount ) )
    
    530
    +    if ( FT_READ_ULONG( region_offset ) ||
    
    531
    +         FT_READ_USHORT( data_count )   )
    
    530 532
           goto Exit;
    
    531 533
     
    
    532 534
         /* we need at least one entry in `itemStore->varData' */
    
    533
    -    if ( !itemStore->dataCount )
    
    535
    +    if ( !data_count )
    
    534 536
         {
    
    535 537
           FT_TRACE2(( "tt_var_load_item_variation_store: missing varData\n" ));
    
    536 538
           error = FT_THROW( Invalid_Table );
    
    ... ... @@ -539,10 +541,10 @@
    539 541
     
    
    540 542
         /* make temporary copy of item variation data offsets; */
    
    541 543
         /* we will parse region list first, then come back     */
    
    542
    -    if ( FT_QNEW_ARRAY( dataOffsetArray, itemStore->dataCount ) )
    
    544
    +    if ( FT_QNEW_ARRAY( dataOffsetArray, data_count ) )
    
    543 545
           goto Exit;
    
    544 546
     
    
    545
    -    for ( i = 0; i < itemStore->dataCount; i++ )
    
    547
    +    for ( i = 0; i < data_count; i++ )
    
    546 548
         {
    
    547 549
           if ( FT_READ_ULONG( dataOffsetArray[i] ) )
    
    548 550
             goto Exit;
    
    ... ... @@ -552,11 +554,11 @@
    552 554
         if ( FT_STREAM_SEEK( offset + region_offset ) )
    
    553 555
           goto Exit;
    
    554 556
     
    
    555
    -    if ( FT_READ_USHORT( itemStore->axisCount )   ||
    
    556
    -         FT_READ_USHORT( itemStore->regionCount ) )
    
    557
    +    if ( FT_READ_USHORT( axis_count )   ||
    
    558
    +         FT_READ_USHORT( region_count ) )
    
    557 559
           goto Exit;
    
    558 560
     
    
    559
    -    if ( itemStore->axisCount != (FT_Long)blend->mmvar->num_axis )
    
    561
    +    if ( axis_count != (FT_Long)blend->mmvar->num_axis )
    
    560 562
         {
    
    561 563
           FT_TRACE2(( "tt_var_load_item_variation_store:"
    
    562 564
                       " number of axes in item variation store\n" ));
    
    ... ... @@ -565,9 +567,10 @@
    565 567
           error = FT_THROW( Invalid_Table );
    
    566 568
           goto Exit;
    
    567 569
         }
    
    570
    +    itemStore->axisCount = axis_count;
    
    568 571
     
    
    569 572
         /* new constraint in OpenType 1.8.4 */
    
    570
    -    if ( itemStore->regionCount >= 32768U )
    
    573
    +    if ( region_count >= 32768U )
    
    571 574
         {
    
    572 575
           FT_TRACE2(( "tt_var_load_item_variation_store:"
    
    573 576
                       " too many variation region tables\n" ));
    
    ... ... @@ -575,16 +578,16 @@
    575 578
           goto Exit;
    
    576 579
         }
    
    577 580
     
    
    578
    -    if ( FT_NEW_ARRAY( itemStore->varRegionList, itemStore->regionCount ) )
    
    581
    +    if ( FT_NEW_ARRAY( itemStore->varRegionList, region_count ) )
    
    579 582
           goto Exit;
    
    583
    +    itemStore->regionCount = region_count;
    
    580 584
     
    
    581 585
         for ( i = 0; i < itemStore->regionCount; i++ )
    
    582 586
         {
    
    583 587
           GX_AxisCoords  axisCoords;
    
    584 588
     
    
    585 589
     
    
    586
    -      if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList,
    
    587
    -                         itemStore->axisCount ) )
    
    590
    +      if ( FT_NEW_ARRAY( itemStore->varRegionList[i].axisList, axis_count ) )
    
    588 591
             goto Exit;
    
    589 592
     
    
    590 593
           axisCoords = itemStore->varRegionList[i].axisList;
    
    ... ... @@ -608,47 +611,53 @@
    608 611
         /* end of region list parse */
    
    609 612
     
    
    610 613
         /* use dataOffsetArray now to parse varData items */
    
    611
    -    if ( FT_NEW_ARRAY( itemStore->varData, itemStore->dataCount ) )
    
    614
    +    if ( FT_NEW_ARRAY( itemStore->varData, data_count ) )
    
    612 615
           goto Exit;
    
    616
    +    itemStore->dataCount = data_count;
    
    613 617
     
    
    614
    -    for ( i = 0; i < itemStore->dataCount; i++ )
    
    618
    +    for ( i = 0; i < data_count; i++ )
    
    615 619
         {
    
    616
    -      varData = &itemStore->varData[i];
    
    620
    +      GX_ItemVarData  varData = &itemStore->varData[i];
    
    621
    +
    
    622
    +      FT_UInt  item_count;
    
    623
    +      FT_UInt  word_delta_count;
    
    624
    +      FT_UInt  region_idx_count;
    
    625
    +
    
    617 626
     
    
    618 627
           if ( FT_STREAM_SEEK( offset + dataOffsetArray[i] ) )
    
    619 628
             goto Exit;
    
    620 629
     
    
    621
    -      if ( FT_READ_USHORT( varData->itemCount )      ||
    
    622
    -           FT_READ_USHORT( wordDeltaCount )          ||
    
    623
    -           FT_READ_USHORT( varData->regionIdxCount ) )
    
    630
    +      if ( FT_READ_USHORT( item_count )       ||
    
    631
    +           FT_READ_USHORT( word_delta_count ) ||
    
    632
    +           FT_READ_USHORT( region_idx_count ) )
    
    624 633
             goto Exit;
    
    625 634
     
    
    626
    -      long_words      = !!( wordDeltaCount & 0x8000 );
    
    627
    -      wordDeltaCount &= 0x7FFF;
    
    635
    +      long_words        = !!( word_delta_count & 0x8000 );
    
    636
    +      word_delta_count &= 0x7FFF;
    
    628 637
     
    
    629 638
           /* check some data consistency */
    
    630
    -      if ( wordDeltaCount > varData->regionIdxCount )
    
    639
    +      if ( word_delta_count > region_idx_count )
    
    631 640
           {
    
    632 641
             FT_TRACE2(( "bad short count %d or region count %d\n",
    
    633
    -                    wordDeltaCount,
    
    634
    -                    varData->regionIdxCount ));
    
    642
    +                    word_delta_count,
    
    643
    +                    region_idx_count ));
    
    635 644
             error = FT_THROW( Invalid_Table );
    
    636 645
             goto Exit;
    
    637 646
           }
    
    638 647
     
    
    639
    -      if ( varData->regionIdxCount > itemStore->regionCount )
    
    648
    +      if ( region_idx_count > itemStore->regionCount )
    
    640 649
           {
    
    641 650
             FT_TRACE2(( "inconsistent regionCount %d in varData[%d]\n",
    
    642
    -                    varData->regionIdxCount,
    
    651
    +                    region_idx_count,
    
    643 652
                         i ));
    
    644 653
             error = FT_THROW( Invalid_Table );
    
    645 654
             goto Exit;
    
    646 655
           }
    
    647 656
     
    
    648 657
           /* parse region indices */
    
    649
    -      if ( FT_NEW_ARRAY( varData->regionIndices,
    
    650
    -                         varData->regionIdxCount ) )
    
    658
    +      if ( FT_NEW_ARRAY( varData->regionIndices, region_idx_count ) )
    
    651 659
             goto Exit;
    
    660
    +      varData->regionIdxCount = region_idx_count;
    
    652 661
     
    
    653 662
           for ( j = 0; j < varData->regionIdxCount; j++ )
    
    654 663
           {
    
    ... ... @@ -664,33 +673,33 @@
    664 673
             }
    
    665 674
           }
    
    666 675
     
    
    667
    -      /* Parse delta set.                                                */
    
    668
    -      /*                                                                 */
    
    669
    -      /* On input, deltas are (wordDeltaCount + regionIdxCount) bytes    */
    
    670
    -      /* each if `long_words` isn't set, and twice as much otherwise.    */
    
    671
    -      /*                                                                 */
    
    672
    -      /* On output, deltas are expanded to `regionIdxCount` shorts each. */
    
    673
    -      if ( FT_NEW_ARRAY( varData->deltaSet,
    
    674
    -                         varData->regionIdxCount * varData->itemCount ) )
    
    676
    +      /* Parse delta set.                                                  */
    
    677
    +      /*                                                                   */
    
    678
    +      /* On input, deltas are (word_delta_count + region_idx_count) bytes  */
    
    679
    +      /* each if `long_words` isn't set, and twice as much otherwise.      */
    
    680
    +      /*                                                                   */
    
    681
    +      /* On output, deltas are expanded to `region_idx_count` shorts each. */
    
    682
    +      if ( FT_NEW_ARRAY( varData->deltaSet, item_count * region_idx_count ) )
    
    675 683
             goto Exit;
    
    684
    +      varData->itemCount = item_count;
    
    676 685
     
    
    677
    -      for ( j = 0; j < varData->itemCount * varData->regionIdxCount; )
    
    686
    +      for ( j = 0; j < item_count * region_idx_count; )
    
    678 687
           {
    
    679 688
             if ( long_words )
    
    680 689
             {
    
    681
    -          for ( k = 0; k < wordDeltaCount; k++, j++ )
    
    690
    +          for ( k = 0; k < word_delta_count; k++, j++ )
    
    682 691
                 if ( FT_READ_LONG( varData->deltaSet[j] ) )
    
    683 692
                   goto Exit;
    
    684
    -          for ( ; k < varData->regionIdxCount; k++, j++ )
    
    693
    +          for ( ; k < region_idx_count; k++, j++ )
    
    685 694
                 if ( FT_READ_SHORT( varData->deltaSet[j] ) )
    
    686 695
                   goto Exit;
    
    687 696
             }
    
    688 697
             else
    
    689 698
             {
    
    690
    -          for ( k = 0; k < wordDeltaCount; k++, j++ )
    
    699
    +          for ( k = 0; k < word_delta_count; k++, j++ )
    
    691 700
                 if ( FT_READ_SHORT( varData->deltaSet[j] ) )
    
    692 701
                   goto Exit;
    
    693
    -          for ( ; k < varData->regionIdxCount; k++, j++ )
    
    702
    +          for ( ; k < region_idx_count; k++, j++ )
    
    694 703
                 if ( FT_READ_CHAR( varData->deltaSet[j] ) )
    
    695 704
                   goto Exit;
    
    696 705
             }
    


  • reply via email to

    [Prev in Thread] Current Thread [Next in Thread]