freetype-commit
[Top][All Lists]
Advanced

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

[Git][freetype/freetype][master] [sfnt] Add SVG document bounds checking


From: Werner Lemberg (@wl)
Subject: [Git][freetype/freetype][master] [sfnt] Add SVG document bounds checking.
Date: Tue, 27 Sep 2022 05:34:14 +0000

Werner Lemberg pushed to branch master at FreeType / FreeType

Commits:

  • bd417007
    by Ben Wagner at 2022-09-27T07:31:32+02:00
    [sfnt] Add SVG document bounds checking.
    
    Add a check that the document content is actually contained within the
    `SVG ` table.  Without this check a malformed font may claim arbitrary
    memory as its document content.
    
    * src/sfnt/ttsvg.c (tt_face_load_svg): Take `numEntries` into account when
    testing 'documentRecord' extents.
    (find_doc): Rename `stream` to `document_records` for clarity.
    (tt_face_load_svg_doc): Split `doc` from `doc_list` pointer for clarity.
    Test that the document content is contained within the table.
    Ensure minimum length of document before testing for gzip format.
    
    Reported as
    
      https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=51812
    

1 changed file:

Changes:

  • src/sfnt/ttsvg.c
    ... ... @@ -114,7 +114,7 @@
    114 114
         FT_TRACE3(( "version: %d\n", svg->version ));
    
    115 115
         FT_TRACE3(( "number of entries: %d\n", svg->num_entries ));
    
    116 116
     
    
    117
    -    if ( offsetToSVGDocumentList +
    
    117
    +    if ( offsetToSVGDocumentList + 2U +
    
    118 118
                svg->num_entries * SVG_DOCUMENT_RECORD_SIZE > table_size )
    
    119 119
           goto InvalidTable;
    
    120 120
     
    
    ... ... @@ -196,7 +196,7 @@
    196 196
     
    
    197 197
     
    
    198 198
       static FT_Error
    
    199
    -  find_doc( FT_Byte*    stream,
    
    199
    +  find_doc( FT_Byte*    document_records,
    
    200 200
                 FT_UShort   num_entries,
    
    201 201
                 FT_UInt     glyph_index,
    
    202 202
                 FT_ULong   *doc_offset,
    
    ... ... @@ -225,8 +225,8 @@
    225 225
           return error;
    
    226 226
         }
    
    227 227
     
    
    228
    -    start_doc = extract_svg_doc( stream + start_index * 12 );
    
    229
    -    end_doc   = extract_svg_doc( stream + end_index * 12 );
    
    228
    +    start_doc = extract_svg_doc( document_records + start_index * 12 );
    
    229
    +    end_doc   = extract_svg_doc( document_records + end_index * 12 );
    
    230 230
     
    
    231 231
         if ( ( compare_svg_doc( start_doc, glyph_index ) == -1 ) ||
    
    232 232
              ( compare_svg_doc( end_doc, glyph_index ) == 1 )    )
    
    ... ... @@ -238,18 +238,18 @@
    238 238
         while ( start_index <= end_index )
    
    239 239
         {
    
    240 240
           i        = ( start_index + end_index ) / 2;
    
    241
    -      mid_doc  = extract_svg_doc( stream + i * 12 );
    
    241
    +      mid_doc  = extract_svg_doc( document_records + i * 12 );
    
    242 242
           comp_res = compare_svg_doc( mid_doc, glyph_index );
    
    243 243
     
    
    244 244
           if ( comp_res == 1 )
    
    245 245
           {
    
    246 246
             start_index = i + 1;
    
    247
    -        start_doc   = extract_svg_doc( stream + start_index * 4 );
    
    247
    +        start_doc   = extract_svg_doc( document_records + start_index * 4 );
    
    248 248
           }
    
    249 249
           else if ( comp_res == -1 )
    
    250 250
           {
    
    251 251
             end_index = i - 1;
    
    252
    -        end_doc   = extract_svg_doc( stream + end_index * 4 );
    
    252
    +        end_doc   = extract_svg_doc( document_records + end_index * 4 );
    
    253 253
           }
    
    254 254
           else
    
    255 255
           {
    
    ... ... @@ -283,38 +283,47 @@
    283 283
       tt_face_load_svg_doc( FT_GlyphSlot  glyph,
    
    284 284
                             FT_UInt       glyph_index )
    
    285 285
       {
    
    286
    -    FT_Byte*   doc_list;        /* pointer to the SVG doc list         */
    
    287
    -    FT_UShort  num_entries;     /* total number of entries in doc list */
    
    288
    -    FT_ULong   doc_offset;
    
    289
    -    FT_ULong   doc_length;
    
    290
    -
    
    291
    -    FT_UShort  start_glyph_id;
    
    292
    -    FT_UShort  end_glyph_id;
    
    293
    -
    
    294 286
         FT_Error   error  = FT_Err_Ok;
    
    295 287
         TT_Face    face   = (TT_Face)glyph->face;
    
    296 288
         FT_Memory  memory = face->root.memory;
    
    297 289
         Svg*       svg    = (Svg*)face->svg;
    
    298 290
     
    
    291
    +    FT_Byte*  doc_list;
    
    292
    +    FT_ULong  doc_limit;
    
    293
    +
    
    294
    +    FT_Byte*   doc;
    
    295
    +    FT_ULong   doc_offset;
    
    296
    +    FT_ULong   doc_length;
    
    297
    +    FT_UShort  doc_start_glyph_id;
    
    298
    +    FT_UShort  doc_end_glyph_id;
    
    299
    +
    
    299 300
         FT_SVG_Document  svg_document = (FT_SVG_Document)glyph->other;
    
    300 301
     
    
    301 302
     
    
    302 303
         FT_ASSERT( !( svg == NULL ) );
    
    303 304
     
    
    304
    -    doc_list    = svg->svg_doc_list;
    
    305
    -    num_entries = FT_NEXT_USHORT( doc_list );
    
    305
    +    doc_list = svg->svg_doc_list;
    
    306 306
     
    
    307
    -    error = find_doc( doc_list, num_entries, glyph_index,
    
    308
    -                                &doc_offset, &doc_length,
    
    309
    -                                &start_glyph_id, &end_glyph_id );
    
    307
    +    error = find_doc( doc_list + 2, svg->num_entries, glyph_index,
    
    308
    +                                    &doc_offset, &doc_length,
    
    309
    +                                    &doc_start_glyph_id, &doc_end_glyph_id );
    
    310 310
         if ( error != FT_Err_Ok )
    
    311 311
           goto Exit;
    
    312 312
     
    
    313
    -    doc_list = svg->svg_doc_list;      /* reset, so we can use it again */
    
    314
    -    doc_list = (FT_Byte*)( doc_list + doc_offset );
    
    313
    +    doc_limit = svg->table_size - ( doc_list - (FT_Byte*)svg->table );
    
    314
    +    if ( doc_offset > doc_limit              ||
    
    315
    +         doc_length > doc_limit - doc_offset )
    
    316
    +    {
    
    317
    +      error = FT_THROW( Invalid_Table );
    
    318
    +      goto Exit;
    
    319
    +    }
    
    320
    +
    
    321
    +    doc = doc_list + doc_offset;
    
    315 322
     
    
    316
    -    if ( ( doc_list[0] == 0x1F ) && ( doc_list[1] == 0x8B )
    
    317
    -                                 && ( doc_list[2] == 0x08 ) )
    
    323
    +    if ( doc_length > 6 &&
    
    324
    +         doc[0] == 0x1F &&
    
    325
    +         doc[1] == 0x8B &&
    
    326
    +         doc[2] == 0x08 )
    
    318 327
         {
    
    319 328
     #ifdef FT_CONFIG_OPTION_USE_ZLIB
    
    320 329
     
    
    ... ... @@ -331,10 +340,10 @@
    331 340
            * little-endian format.
    
    332 341
            */
    
    333 342
           FT_TRACE4(( "SVG document is GZIP compressed\n" ));
    
    334
    -      uncomp_size = (FT_ULong)doc_list[doc_length - 1] << 24 |
    
    335
    -                    (FT_ULong)doc_list[doc_length - 2] << 16 |
    
    336
    -                    (FT_ULong)doc_list[doc_length - 3] << 8  |
    
    337
    -                    (FT_ULong)doc_list[doc_length - 4];
    
    343
    +      uncomp_size = (FT_ULong)doc[doc_length - 1] << 24 |
    
    344
    +                    (FT_ULong)doc[doc_length - 2] << 16 |
    
    345
    +                    (FT_ULong)doc[doc_length - 3] << 8  |
    
    346
    +                    (FT_ULong)doc[doc_length - 4];
    
    338 347
     
    
    339 348
           if ( FT_QALLOC( uncomp_buffer, uncomp_size ) )
    
    340 349
             goto Exit;
    
    ... ... @@ -342,7 +351,7 @@
    342 351
           error = FT_Gzip_Uncompress( memory,
    
    343 352
                                       uncomp_buffer,
    
    344 353
                                       &uncomp_size,
    
    345
    -                                  doc_list,
    
    354
    +                                  doc,
    
    346 355
                                       doc_length );
    
    347 356
           if ( error )
    
    348 357
           {
    
    ... ... @@ -353,7 +362,7 @@
    353 362
     
    
    354 363
           glyph->internal->flags |= FT_GLYPH_OWN_GZIP_SVG;
    
    355 364
     
    
    356
    -      doc_list   = uncomp_buffer;
    
    365
    +      doc        = uncomp_buffer;
    
    357 366
           doc_length = uncomp_size;
    
    358 367
     
    
    359 368
     #else /* !FT_CONFIG_OPTION_USE_ZLIB */
    
    ... ... @@ -364,14 +373,14 @@
    364 373
     #endif /* !FT_CONFIG_OPTION_USE_ZLIB */
    
    365 374
         }
    
    366 375
     
    
    367
    -    svg_document->svg_document        = doc_list;
    
    376
    +    svg_document->svg_document        = doc;
    
    368 377
         svg_document->svg_document_length = doc_length;
    
    369 378
     
    
    370 379
         svg_document->metrics      = glyph->face->size->metrics;
    
    371 380
         svg_document->units_per_EM = glyph->face->units_per_EM;
    
    372 381
     
    
    373
    -    svg_document->start_glyph_id = start_glyph_id;
    
    374
    -    svg_document->end_glyph_id   = end_glyph_id;
    
    382
    +    svg_document->start_glyph_id = doc_start_glyph_id;
    
    383
    +    svg_document->end_glyph_id   = doc_end_glyph_id;
    
    375 384
     
    
    376 385
         svg_document->transform.xx = 0x10000;
    
    377 386
         svg_document->transform.xy = 0;
    
    ... ... @@ -381,10 +390,10 @@
    381 390
         svg_document->delta.x = 0;
    
    382 391
         svg_document->delta.y = 0;
    
    383 392
     
    
    384
    -    FT_TRACE5(( "start_glyph_id: %d\n", start_glyph_id ));
    
    385
    -    FT_TRACE5(( "end_glyph_id:   %d\n", end_glyph_id ));
    
    393
    +    FT_TRACE5(( "start_glyph_id: %d\n", doc_start_glyph_id ));
    
    394
    +    FT_TRACE5(( "end_glyph_id:   %d\n", doc_end_glyph_id ));
    
    386 395
         FT_TRACE5(( "svg_document:\n" ));
    
    387
    -    FT_TRACE5(( " %.*s\n", (FT_UInt)doc_length, doc_list ));
    
    396
    +    FT_TRACE5(( " %.*s\n", (FT_UInt)doc_length, doc ));
    
    388 397
     
    
    389 398
         glyph->other = svg_document;
    
    390 399
     
    


  • reply via email to

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