freetype-commit
[Top][All Lists]
Advanced

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

[Git][freetype/freetype][master] [psaux] Guard and trace AFM kern data a


From: Werner Lemberg (@wl)
Subject: [Git][freetype/freetype][master] [psaux] Guard and trace AFM kern data allocation.
Date: Tue, 25 May 2021 09:28:14 +0000

Werner Lemberg pushed to branch master at FreeType / FreeType

Commits:

3 changed files:

Changes:

  • ChangeLog
    1
    +2021-05-25  Werner Lemberg  <wl@gnu.org>
    
    2
    +
    
    3
    +	[psaux] Guard and trace AFM kern data allocation.
    
    4
    +
    
    5
    +	Reported as
    
    6
    +
    
    7
    +	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=31543
    
    8
    +
    
    9
    +	* include/freetype/internal/fttrace.h: Add 'afmparse' trace
    
    10
    +	component.
    
    11
    +
    
    12
    +	* src/psaux/afmparse.c (FT_COMPONENT): Define.
    
    13
    +	(afm_parse_track_kern, afm_parse_kern_pairs): Protect against
    
    14
    +	allocations bombs.
    
    15
    +	Add tracing.
    
    16
    +	(afm_parse_kern_data): Don't allow multiple kern data sections.
    
    17
    +
    
    1 18
     2021-05-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
    
    2 19
     
    
    3 20
     	* meson.build (ft2_public_headers): Add missing `ftcid.h'.
    

  • include/freetype/internal/fttrace.h
    ... ... @@ -83,6 +83,7 @@ FT_TRACE_DEF( t1objs )
    83 83
     FT_TRACE_DEF( t1parse )
    
    84 84
     
    
    85 85
       /* PostScript helper module `psaux' */
    
    86
    +FT_TRACE_DEF( afmparse )
    
    86 87
     FT_TRACE_DEF( cffdecode )
    
    87 88
     FT_TRACE_DEF( psconv )
    
    88 89
     FT_TRACE_DEF( psobjs )
    

  • src/psaux/afmparse.c
    ... ... @@ -27,6 +27,16 @@
    27 27
     #include "psauxerr.h"
    
    28 28
     
    
    29 29
     
    
    30
    +  /**************************************************************************
    
    31
    +   *
    
    32
    +   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
    
    33
    +   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
    
    34
    +   * messages during execution.
    
    35
    +   */
    
    36
    +#undef  FT_COMPONENT
    
    37
    +#define FT_COMPONENT  afmparse
    
    38
    +
    
    39
    +
    
    30 40
       /**************************************************************************
    
    31 41
        *
    
    32 42
        * AFM_Stream
    
    ... ... @@ -586,21 +596,38 @@
    586 596
       static FT_Error
    
    587 597
       afm_parse_track_kern( AFM_Parser  parser )
    
    588 598
       {
    
    589
    -    AFM_FontInfo   fi = parser->FontInfo;
    
    599
    +    AFM_FontInfo   fi     = parser->FontInfo;
    
    600
    +    AFM_Stream     stream = parser->stream;
    
    590 601
         AFM_TrackKern  tk;
    
    591
    -    char*          key;
    
    592
    -    FT_Offset      len;
    
    593
    -    int            n = -1;
    
    594
    -    FT_Int         tmp;
    
    602
    +
    
    603
    +    char*      key;
    
    604
    +    FT_Offset  len;
    
    605
    +    int        n = -1;
    
    606
    +    FT_Int     tmp;
    
    595 607
     
    
    596 608
     
    
    597 609
         if ( afm_parser_read_int( parser, &tmp ) )
    
    598 610
             goto Fail;
    
    599 611
     
    
    600 612
         if ( tmp < 0 )
    
    613
    +    {
    
    614
    +      FT_ERROR(( "afm_parse_track_kern: invalid number of track kerns\n" ));
    
    601 615
           goto Fail;
    
    616
    +    }
    
    602 617
     
    
    603 618
         fi->NumTrackKern = (FT_UInt)tmp;
    
    619
    +    FT_TRACE3(( "afm_parse_track_kern: %u track kern%s expected\n",
    
    620
    +                fi->NumTrackKern,
    
    621
    +                fi->NumTrackKern == 1 ? "" : "s" ));
    
    622
    +
    
    623
    +    /* Rough sanity check: The minimum line length of the `TrackKern` */
    
    624
    +    /* command is 20 characters (including the EOL character).        */
    
    625
    +    if ( ( stream->limit - stream->cursor ) / 20 < fi->NumTrackKern )
    
    626
    +    {
    
    627
    +      FT_ERROR(( "afm_parse_track_kern:"
    
    628
    +                 " number of track kern entries exceeds stream size\n" ));
    
    629
    +      goto Fail;
    
    630
    +    }
    
    604 631
     
    
    605 632
         if ( fi->NumTrackKern )
    
    606 633
         {
    
    ... ... @@ -623,7 +650,10 @@
    623 650
             n++;
    
    624 651
     
    
    625 652
             if ( n >= (int)fi->NumTrackKern )
    
    626
    -          goto Fail;
    
    653
    +          {
    
    654
    +            FT_ERROR(( "afm_parse_track_kern: too many track kern data\n" ));
    
    655
    +            goto Fail;
    
    656
    +          }
    
    627 657
     
    
    628 658
             tk = fi->TrackKerns + n;
    
    629 659
     
    
    ... ... @@ -633,7 +663,12 @@
    633 663
             shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
    
    634 664
             shared_vals[4].type = AFM_VALUE_TYPE_FIXED;
    
    635 665
             if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 )
    
    666
    +        {
    
    667
    +          FT_ERROR(( "afm_parse_track_kern:"
    
    668
    +                     " insufficient number of parameters for entry %d\n",
    
    669
    +                     n ));
    
    636 670
               goto Fail;
    
    671
    +        }
    
    637 672
     
    
    638 673
             tk->degree     = shared_vals[0].u.i;
    
    639 674
             tk->min_ptsize = shared_vals[1].u.f;
    
    ... ... @@ -646,7 +681,19 @@
    646 681
           case AFM_TOKEN_ENDTRACKKERN:
    
    647 682
           case AFM_TOKEN_ENDKERNDATA:
    
    648 683
           case AFM_TOKEN_ENDFONTMETRICS:
    
    649
    -        fi->NumTrackKern = (FT_UInt)( n + 1 );
    
    684
    +        tmp = n + 1;
    
    685
    +        if ( (FT_UInt)tmp != fi->NumTrackKern )
    
    686
    +        {
    
    687
    +          FT_TRACE1(( "afm_parse_track_kern: %s%d track kern entr%s seen\n",
    
    688
    +                      tmp == 0 ? "" : "only ",
    
    689
    +                      tmp,
    
    690
    +                      tmp == 1 ? "y" : "ies" ));
    
    691
    +          fi->NumTrackKern = (FT_UInt)tmp;
    
    692
    +        }
    
    693
    +        else
    
    694
    +          FT_TRACE3(( "afm_parse_track_kern: %d track kern entr%s seen\n",
    
    695
    +                      tmp,
    
    696
    +                      tmp == 1 ? "y" : "ies" ));
    
    650 697
             return FT_Err_Ok;
    
    651 698
     
    
    652 699
           case AFM_TOKEN_UNKNOWN:
    
    ... ... @@ -690,7 +737,8 @@
    690 737
       static FT_Error
    
    691 738
       afm_parse_kern_pairs( AFM_Parser  parser )
    
    692 739
       {
    
    693
    -    AFM_FontInfo  fi = parser->FontInfo;
    
    740
    +    AFM_FontInfo  fi     = parser->FontInfo;
    
    741
    +    AFM_Stream    stream = parser->stream;
    
    694 742
         AFM_KernPair  kp;
    
    695 743
         char*         key;
    
    696 744
         FT_Offset     len;
    
    ... ... @@ -702,9 +750,25 @@
    702 750
           goto Fail;
    
    703 751
     
    
    704 752
         if ( tmp < 0 )
    
    753
    +    {
    
    754
    +      FT_ERROR(( "afm_parse_kern_pairs: invalid number of kern pairs\n" ));
    
    705 755
           goto Fail;
    
    756
    +    }
    
    706 757
     
    
    707 758
         fi->NumKernPair = (FT_UInt)tmp;
    
    759
    +    FT_TRACE3(( "afm_parse_kern_pairs: %u kern pair%s expected\n",
    
    760
    +                fi->NumKernPair,
    
    761
    +                fi->NumKernPair == 1 ? "" : "s" ));
    
    762
    +
    
    763
    +    /* Rough sanity check: The minimum line length of the `KP`,    */
    
    764
    +    /* `KPH`,`KPX`, and `KPY` commands is 10 characters (including */
    
    765
    +    /* the EOL character).                                         */
    
    766
    +    if ( ( stream->limit - stream->cursor ) / 10 < fi->NumKernPair )
    
    767
    +    {
    
    768
    +      FT_ERROR(( "afm_parse_kern_pairs:"
    
    769
    +                 " number of kern pairs exceeds stream size\n" ));
    
    770
    +      goto Fail;
    
    771
    +    }
    
    708 772
     
    
    709 773
         if ( fi->NumKernPair )
    
    710 774
         {
    
    ... ... @@ -734,7 +798,10 @@
    734 798
               n++;
    
    735 799
     
    
    736 800
               if ( n >= (int)fi->NumKernPair )
    
    801
    +          {
    
    802
    +            FT_ERROR(( "afm_parse_kern_pairs: too many kern pairs\n" ));
    
    737 803
                 goto Fail;
    
    804
    +          }
    
    738 805
     
    
    739 806
               kp = fi->KernPairs + n;
    
    740 807
     
    
    ... ... @@ -744,7 +811,12 @@
    744 811
               shared_vals[3].type = AFM_VALUE_TYPE_INTEGER;
    
    745 812
               r = afm_parser_read_vals( parser, shared_vals, 4 );
    
    746 813
               if ( r < 3 )
    
    814
    +          {
    
    815
    +            FT_ERROR(( "afm_parse_kern_pairs:"
    
    816
    +                       " insufficient number of parameters for entry %d\n",
    
    817
    +                       n ));
    
    747 818
                 goto Fail;
    
    819
    +          }
    
    748 820
     
    
    749 821
               /* index values can't be negative */
    
    750 822
               kp->index1 = shared_vals[0].u.u;
    
    ... ... @@ -766,7 +838,20 @@
    766 838
           case AFM_TOKEN_ENDKERNPAIRS:
    
    767 839
           case AFM_TOKEN_ENDKERNDATA:
    
    768 840
           case AFM_TOKEN_ENDFONTMETRICS:
    
    769
    -        fi->NumKernPair = (FT_UInt)( n + 1 );
    
    841
    +        tmp = n + 1;
    
    842
    +        if ( (FT_UInt)tmp != fi->NumKernPair )
    
    843
    +        {
    
    844
    +          FT_TRACE1(( "afm_parse_kern_pairs: %s%d kern pair%s seen\n",
    
    845
    +                      tmp == 0 ? "" : "only ",
    
    846
    +                      tmp,
    
    847
    +                      tmp == 1 ? "" : "s" ));
    
    848
    +          fi->NumKernPair = (FT_UInt)tmp;
    
    849
    +        }
    
    850
    +        else
    
    851
    +          FT_TRACE3(( "afm_parse_kern_pairs: %d kern pair%s seen\n",
    
    852
    +                      tmp,
    
    853
    +                      tmp == 1 ? "" : "s" ));
    
    854
    +
    
    770 855
             ft_qsort( fi->KernPairs, fi->NumKernPair,
    
    771 856
                       sizeof ( AFM_KernPairRec ),
    
    772 857
                       afm_compare_kern_pairs );
    
    ... ... @@ -792,22 +877,43 @@
    792 877
         char*      key;
    
    793 878
         FT_Offset  len;
    
    794 879
     
    
    880
    +    int  have_trackkern = 0;
    
    881
    +    int  have_kernpairs = 0;
    
    882
    +
    
    795 883
     
    
    796 884
         while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
    
    797 885
         {
    
    798 886
           switch ( afm_tokenize( key, len ) )
    
    799 887
           {
    
    800 888
           case AFM_TOKEN_STARTTRACKKERN:
    
    889
    +        if ( have_trackkern )
    
    890
    +        {
    
    891
    +          FT_ERROR(( "afm_parse_kern_data:"
    
    892
    +                     " invalid second horizontal track kern section\n" ));
    
    893
    +          goto Fail;
    
    894
    +        }
    
    895
    +
    
    801 896
             error = afm_parse_track_kern( parser );
    
    802 897
             if ( error )
    
    803 898
               return error;
    
    899
    +
    
    900
    +        have_trackkern = 1;
    
    804 901
             break;
    
    805 902
     
    
    806 903
           case AFM_TOKEN_STARTKERNPAIRS:
    
    807 904
           case AFM_TOKEN_STARTKERNPAIRS0:
    
    905
    +        if ( have_kernpairs )
    
    906
    +        {
    
    907
    +          FT_ERROR(( "afm_parse_kern_data:"
    
    908
    +                     " invalid second horizontal kern pair section\n" ));
    
    909
    +          goto Fail;
    
    910
    +        }
    
    911
    +
    
    808 912
             error = afm_parse_kern_pairs( parser );
    
    809 913
             if ( error )
    
    810 914
               return error;
    
    915
    +
    
    916
    +        have_kernpairs = 1;
    
    811 917
             break;
    
    812 918
     
    
    813 919
           case AFM_TOKEN_ENDKERNDATA:
    


  • reply via email to

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