freetype-commit
[Top][All Lists]
Advanced

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

[Git][freetype/freetype][master] [truetype/GX] Read points and deltas mo


From: Alexei Podtelezhnikov (@apodtele)
Subject: [Git][freetype/freetype][master] [truetype/GX] Read points and deltas more carefully.
Date: Wed, 31 Jul 2024 01:58:17 +0000

Alexei Podtelezhnikov pushed to branch master at FreeType / FreeType

Commits:

  • 5e116bb0
    by Alexei Podtelezhnikov (Алексей Подтележников) at 2024-07-30T21:51:51-04:00
    [truetype/GX] Read points and deltas more carefully.
    
    Hopefully fixes newly introduced buffer overflows:
      https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=70807
      https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=70809
    
    * src/truetype/ttgxvar.c (ft_var_readpacked{points,deltas}): Explicitly
    check stream frame limits and modify run counting.
    

1 changed file:

Changes:

  • src/truetype/ttgxvar.c
    ... ... @@ -129,9 +129,6 @@
    129 129
        *   stream ::
    
    130 130
        *     The data stream.
    
    131 131
        *
    
    132
    -   *   size ::
    
    133
    -   *     The size of the table holding the data.
    
    134
    -   *
    
    135 132
        * @Output:
    
    136 133
        *   point_cnt ::
    
    137 134
        *     The number of points read.  A zero value means that
    
    ... ... @@ -144,12 +141,11 @@
    144 141
        */
    
    145 142
       static FT_UShort*
    
    146 143
       ft_var_readpackedpoints( FT_Stream  stream,
    
    147
    -                           FT_ULong   size,
    
    148 144
                                FT_UInt   *point_cnt )
    
    149 145
       {
    
    150 146
         FT_UShort *points = NULL;
    
    151 147
         FT_UInt    n;
    
    152
    -    FT_UInt    runcnt;
    
    148
    +    FT_UInt    runcnt, cnt;
    
    153 149
         FT_UInt    i, j;
    
    154 150
         FT_UShort  first;
    
    155 151
         FT_Byte*   p;
    
    ... ... @@ -170,59 +166,60 @@
    170 166
           n  |= FT_GET_BYTE();
    
    171 167
         }
    
    172 168
     
    
    173
    -    if ( n > size )
    
    174
    -    {
    
    175
    -      FT_TRACE1(( "ft_var_readpackedpoints: number of points too large\n" ));
    
    176
    -      return NULL;
    
    177
    -    }
    
    178
    -
    
    179
    -    /* in the nested loops below we increase `i' twice; */
    
    180
    -    /* it is faster to simply allocate one more slot    */
    
    181
    -    /* than to add another test within the loop         */
    
    182
    -    if ( FT_QNEW_ARRAY( points, n + 1 ) )
    
    169
    +    if ( FT_QNEW_ARRAY( points, n ) )
    
    183 170
           return NULL;
    
    184 171
     
    
    185
    -    *point_cnt = n;
    
    186
    -
    
    187 172
         p     = stream->cursor;
    
    188 173
         first = 0;
    
    189 174
         i     = 0;
    
    190 175
         while ( i < n )
    
    191 176
         {
    
    177
    +      if ( p >= stream->limit )
    
    178
    +        goto Fail;
    
    179
    +
    
    192 180
           runcnt = FT_NEXT_BYTE( p );
    
    181
    +      cnt    = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
    
    182
    +
    
    183
    +      /* first point not included in run count */
    
    184
    +      cnt++;
    
    185
    +      if ( i + cnt > n )
    
    186
    +        cnt = n - i;
    
    187
    +
    
    193 188
           if ( runcnt & GX_PT_POINTS_ARE_WORDS )
    
    194 189
           {
    
    195
    -        runcnt     &= GX_PT_POINT_RUN_COUNT_MASK;
    
    196
    -        first      += FT_NEXT_USHORT( p );
    
    197
    -        points[i++] = first;
    
    190
    +        if ( p + 2 * cnt > stream->limit )
    
    191
    +          goto Fail;
    
    198 192
     
    
    199
    -        /* first point not included in run count */
    
    200
    -        for ( j = 0; j < runcnt; j++ )
    
    193
    +        for ( j = 0; j < cnt; j++ )
    
    201 194
             {
    
    202 195
               first      += FT_NEXT_USHORT( p );
    
    203 196
               points[i++] = first;
    
    204
    -          if ( i >= n )
    
    205
    -            break;
    
    206 197
             }
    
    207 198
           }
    
    208 199
           else
    
    209 200
           {
    
    210
    -        first      += FT_NEXT_BYTE( p );
    
    211
    -        points[i++] = first;
    
    201
    +        if ( p + cnt > stream->limit )
    
    202
    +          goto Fail;
    
    212 203
     
    
    213
    -        for ( j = 0; j < runcnt; j++ )
    
    204
    +        for ( j = 0; j < cnt; j++ )
    
    214 205
             {
    
    215 206
               first      += FT_NEXT_BYTE( p );
    
    216 207
               points[i++] = first;
    
    217
    -          if ( i >= n )
    
    218
    -            break;
    
    219 208
             }
    
    220 209
           }
    
    221 210
         }
    
    222 211
     
    
    223 212
         stream->cursor = p;
    
    224 213
     
    
    214
    +    *point_cnt = n;
    
    215
    +
    
    225 216
         return points;
    
    217
    +
    
    218
    +  Fail:
    
    219
    +    FT_TRACE1(( "ft_var_readpackedpoints: invalid table\n" ));
    
    220
    +
    
    221
    +    FT_FREE( points );
    
    222
    +    return NULL;
    
    226 223
       }
    
    227 224
     
    
    228 225
     
    
    ... ... @@ -244,9 +241,6 @@
    244 241
        *   stream ::
    
    245 242
        *     The data stream.
    
    246 243
        *
    
    247
    -   *   size ::
    
    248
    -   *     The size of the table holding the data.
    
    249
    -   *
    
    250 244
        *   delta_cnt ::
    
    251 245
        *     The number of deltas to be read.
    
    252 246
        *
    
    ... ... @@ -262,13 +256,11 @@
    262 256
        */
    
    263 257
       static FT_Fixed*
    
    264 258
       ft_var_readpackeddeltas( FT_Stream  stream,
    
    265
    -                           FT_ULong   size,
    
    266 259
                                FT_UInt    delta_cnt )
    
    267 260
       {
    
    268 261
         FT_Fixed  *deltas = NULL;
    
    269 262
         FT_UInt    runcnt, cnt;
    
    270 263
         FT_UInt    i, j;
    
    271
    -    FT_UInt    bytes_used;
    
    272 264
         FT_Byte*   p;
    
    273 265
         FT_Memory  memory = stream->memory;
    
    274 266
         FT_Error   error;
    
    ... ... @@ -277,64 +269,44 @@
    277 269
         if ( FT_QNEW_ARRAY( deltas, delta_cnt ) )
    
    278 270
           return NULL;
    
    279 271
     
    
    280
    -    p          = stream->cursor;
    
    281
    -    i          = 0;
    
    282
    -    bytes_used = 0;
    
    283
    -
    
    284
    -    while ( i < delta_cnt && bytes_used < size )
    
    272
    +    p = stream->cursor;
    
    273
    +    i = 0;
    
    274
    +    while ( i < delta_cnt )
    
    285 275
         {
    
    276
    +      if ( p >= stream->limit )
    
    277
    +      {
    
    278
    +        goto Fail;
    
    279
    +      }
    
    280
    +
    
    286 281
           runcnt = FT_NEXT_BYTE( p );
    
    287 282
           cnt    = runcnt & GX_DT_DELTA_RUN_COUNT_MASK;
    
    288 283
     
    
    289
    -      bytes_used++;
    
    284
    +      /* first point not included in run count */
    
    285
    +      cnt++;
    
    286
    +      if ( i + cnt > delta_cnt )
    
    287
    +        cnt = delta_cnt - i;
    
    290 288
     
    
    291 289
           if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
    
    292 290
           {
    
    293
    -        /* `cnt` + 1 zeroes get added */
    
    294
    -        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
    
    291
    +        for ( j = 0; j < cnt; j++ )
    
    295 292
               deltas[i++] = 0;
    
    296 293
           }
    
    297 294
           else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
    
    298 295
           {
    
    299
    -        /* `cnt` + 1 shorts from the stack */
    
    300
    -        bytes_used += 2 * ( cnt + 1 );
    
    301
    -        if ( bytes_used > size )
    
    302
    -        {
    
    303
    -          FT_TRACE1(( "ft_var_readpackeddeltas:"
    
    304
    -                      " number of short deltas too large\n" ));
    
    296
    +        if ( p + 2 * cnt > stream->limit )
    
    305 297
               goto Fail;
    
    306
    -        }
    
    307 298
     
    
    308
    -        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
    
    299
    +        for ( j = 0; j < cnt; j++ )
    
    309 300
               deltas[i++] = FT_intToFixed( FT_NEXT_SHORT( p ) );
    
    310 301
           }
    
    311 302
           else
    
    312 303
           {
    
    313
    -        /* `cnt` + 1 signed bytes from the stack */
    
    314
    -        bytes_used += cnt + 1;
    
    315
    -        if ( bytes_used > size )
    
    316
    -        {
    
    317
    -          FT_TRACE1(( "ft_var_readpackeddeltas:"
    
    318
    -                      " number of byte deltas too large\n" ));
    
    304
    +        if ( p + cnt > stream->limit )
    
    319 305
               goto Fail;
    
    320
    -        }
    
    321 306
     
    
    322
    -        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
    
    307
    +        for ( j = 0; j < cnt; j++ )
    
    323 308
               deltas[i++] = FT_intToFixed( FT_NEXT_CHAR( p ) );
    
    324 309
           }
    
    325
    -
    
    326
    -      if ( j <= cnt )
    
    327
    -      {
    
    328
    -        FT_TRACE1(( "ft_var_readpackeddeltas:"
    
    329
    -                    " number of deltas too large\n" ));
    
    330
    -        goto Fail;
    
    331
    -      }
    
    332
    -    }
    
    333
    -
    
    334
    -    if ( i < delta_cnt )
    
    335
    -    {
    
    336
    -      FT_TRACE1(( "ft_var_readpackeddeltas: not enough deltas\n" ));
    
    337
    -      goto Fail;
    
    338 310
         }
    
    339 311
     
    
    340 312
         stream->cursor = p;
    
    ... ... @@ -342,6 +314,8 @@
    342 314
         return deltas;
    
    343 315
     
    
    344 316
       Fail:
    
    317
    +    FT_TRACE1(( "ft_var_readpackeddeltas: invalid table\n" ));
    
    318
    +
    
    345 319
         FT_FREE( deltas );
    
    346 320
         return NULL;
    
    347 321
       }
    
    ... ... @@ -3612,9 +3586,8 @@
    3612 3586
     
    
    3613 3587
           FT_Stream_SeekSet( stream, offsetToData );
    
    3614 3588
     
    
    3615
    -      sharedpoints = ft_var_readpackedpoints( stream,
    
    3616
    -                                              table_len,
    
    3617
    -                                              &spoint_count );
    
    3589
    +      sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
    
    3590
    +
    
    3618 3591
           offsetToData = FT_Stream_FTell( stream );
    
    3619 3592
     
    
    3620 3593
           FT_Stream_SeekSet( stream, here );
    
    ... ... @@ -3688,9 +3661,7 @@
    3688 3661
     
    
    3689 3662
           if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
    
    3690 3663
           {
    
    3691
    -        localpoints = ft_var_readpackedpoints( stream,
    
    3692
    -                                               table_len,
    
    3693
    -                                               &point_count );
    
    3664
    +        localpoints = ft_var_readpackedpoints( stream, &point_count );
    
    3694 3665
             points      = localpoints;
    
    3695 3666
           }
    
    3696 3667
           else
    
    ... ... @@ -3701,7 +3672,6 @@
    3701 3672
           }
    
    3702 3673
     
    
    3703 3674
           deltas = ft_var_readpackeddeltas( stream,
    
    3704
    -                                        table_len,
    
    3705 3675
                                             point_count == 0 ? face->cvt_size
    
    3706 3676
                                                              : point_count );
    
    3707 3677
     
    
    ... ... @@ -4150,9 +4120,8 @@
    4150 4120
     
    
    4151 4121
           FT_Stream_SeekSet( stream, offsetToData );
    
    4152 4122
     
    
    4153
    -      sharedpoints = ft_var_readpackedpoints( stream,
    
    4154
    -                                              blend->gvar_size,
    
    4155
    -                                              &spoint_count );
    
    4123
    +      sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
    
    4124
    +
    
    4156 4125
           offsetToData = FT_Stream_FTell( stream );
    
    4157 4126
     
    
    4158 4127
           FT_Stream_SeekSet( stream, here );
    
    ... ... @@ -4236,9 +4205,7 @@
    4236 4205
     
    
    4237 4206
           if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
    
    4238 4207
           {
    
    4239
    -        localpoints = ft_var_readpackedpoints( stream,
    
    4240
    -                                               blend->gvar_size,
    
    4241
    -                                               &point_count );
    
    4208
    +        localpoints = ft_var_readpackedpoints( stream, &point_count );
    
    4242 4209
             points      = localpoints;
    
    4243 4210
           }
    
    4244 4211
           else
    
    ... ... @@ -4248,11 +4215,9 @@
    4248 4215
           }
    
    4249 4216
     
    
    4250 4217
           deltas_x = ft_var_readpackeddeltas( stream,
    
    4251
    -                                          blend->gvar_size,
    
    4252 4218
                                               point_count == 0 ? n_points
    
    4253 4219
                                                                : point_count );
    
    4254 4220
           deltas_y = ft_var_readpackeddeltas( stream,
    
    4255
    -                                          blend->gvar_size,
    
    4256 4221
                                               point_count == 0 ? n_points
    
    4257 4222
                                                                : point_count );
    
    4258 4223
     
    


  • reply via email to

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