Wed 12 Nov 2014 06:59:14 PM UTC, original submission:
In freetype/src/sfnt/ttsbit.c, the following code responsible for parsing embedded bitmaps (so-called "sbits") is found:
323: FT_ULong strike_index_array;
324: FT_ULong strike_index_count;
...
377: decoder->strike_index_array = FT_NEXT_ULONG( p );
378: p += 4;
379: decoder->strike_index_count = FT_NEXT_ULONG( p );
380: p += 34;
381: decoder->bit_depth = *p;
382:
383: if ( decoder->strike_index_array > face->sbit_table_size ||
384: decoder->strike_index_array + 8 * decoder->strike_index_count >
385: face->sbit_table_size )
386: error = FT_THROW( Invalid_File_Format );
Note that the "strike_index_count" field is a fully controlled 32-bit variable, so if it is set to >= 0x20000000 in the input file, the "8 * decoder->strike_index_count" expression overflows on 32-bit builds of FreeType. Furthermore, the overall "decoder->strike_index_array + 8 * decoder->strike_index_count" expression can also overflow for smaller values of "strike_index_count", depending on "strike_index_array".
This can be used to bypass the sanity check and later trigger an out-of-bounds read in the "tt_sbit_decoder_load_image" function:
1059: FT_Byte* p = decoder->eblc_base + decoder->strike_index_array;
1060: FT_Byte* p_limit = decoder->eblc_limit;
1061: FT_ULong num_ranges = decoder->strike_index_count;
...
1066: for ( ; num_ranges > 0; num_ranges-- )
1067: {
1068: start = FT_NEXT_USHORT( p );
1069: end = FT_NEXT_USHORT( p );
1070:
1071: if ( glyph_index >= start && glyph_index <= end )
1072: goto FoundRange;
1073:
1074: p += 4; /* ignore index offset */
1075: }
Specifically, the "start" and "end" variables can be loaded from outside of the allocated buffer, if no corresponding glyph range is found inside of it. This can be used to crash the program using FreeType, or potentially disclose information about the contents of adjacent heap memory chunks.
|