[pfr] Add some safety guards (#46302).

* src/pfr/pfrload.h (PFR_CHECK): Rename to...
(PFR_CHECK_SIZE): ... this.
(PFR_SIZE): [!PFR_CONFIG_NO_CHECKS]: Define to PFR_CHECK_SIZE.

* src/pfr/pfrload.c (pfr_log_font_count): Check `count'.
(pfr_extra_item_load_kerning_pairs): Remove tracing message.
(pfr_phy_font_load): Use PFR_CHECK_SIZE where appropriate.
Allocate `chars' after doing a size checks.

* src/pfr/pfrsbit.c (pfr_load_bitmap_bits): Move test for invalid
bitmap format to...
(pfr_slot_load_bitmap): ... this function.
Check bitmap size.
This commit is contained in:
Werner Lemberg 2015-10-27 21:04:48 +01:00
parent 4a3fce93c2
commit fba29fabb3
4 changed files with 178 additions and 14 deletions

View File

@ -1,3 +1,21 @@
2015-10-27 Werner Lemberg <wl@gnu.org>
[pfr] Add some safety guards (#46302).
* src/pfr/pfrload.h (PFR_CHECK): Rename to...
(PFR_CHECK_SIZE): ... this.
(PFR_SIZE): [!PFR_CONFIG_NO_CHECKS]: Define to PFR_CHECK_SIZE.
* src/pfr/pfrload.c (pfr_log_font_count): Check `count'.
(pfr_extra_item_load_kerning_pairs): Remove tracing message.
(pfr_phy_font_load): Use PFR_CHECK_SIZE where appropriate.
Allocate `chars' after doing a size checks.
* src/pfr/pfrsbit.c (pfr_load_bitmap_bits): Move test for invalid
bitmap format to...
(pfr_slot_load_bitmap): ... this function.
Check bitmap size.
2015-10-26 Werner Lemberg <wl@gnu.org>
[truetype] Fix sanitizing logic for `loca' (#46223).

View File

@ -26,6 +26,93 @@
#define FT_COMPONENT trace_pfr
/*
* The overall structure of a PFR file is as follows.
*
* PFR header
* 58 bytes (contains nPhysFonts)
*
* Logical font directory (size at most 2^16 bytes)
* 2 bytes (nLogFonts)
* + nLogFonts * 5 bytes
*
* ==> nLogFonts <= 13106
*
* Logical font section (size at most 2^24 bytes)
* nLogFonts * logFontRecord
*
* logFontRecord (size at most 2^16 bytes)
* 12 bytes (fontMatrix)
* + 1 byte (flags)
* + 0-5 bytes (depending on `flags')
* + 0-(1+255*(2+255)) = 0-65536 (depending on `flags')
* + 5 bytes (physical font info)
* + 0-1 bytes (depending on PFR header)
*
* ==> minimum size 18 bytes
*
* Physical font section (size at most 2^24 bytes)
* nPhysFonts * (physFontRecord
* + nBitmapSizes * nBmapChars * bmapCharRecord)
*
* physFontRecord (size at most 2^24 bytes)
* 14 bytes (font info)
* + 1 byte (flags)
* + 0-2 (depending on `flags')
* + 0-? (structure too complicated to be shown here; depending on
* `flags'; contains `nBitmapSizes' and `nBmapChars')
* + 3 bytes (nAuxBytes)
* + nAuxBytes
* + 1 byte (nBlueValues)
* + 2 * nBlueValues
* + 6 bytes (hinting data)
* + 2 bytes (nCharacters)
* + nCharacters * (4-10 bytes) (depending on `flags')
*
* ==> minimum size 27 bytes
*
* bmapCharRecord
* 4-7 bytes
*
* Glyph program strings (three possible types: simpleGps, compoundGps,
* and bitmapGps; size at most 2^24 bytes)
* simpleGps (size at most 2^16 bytes)
* 1 byte (flags)
* 1-2 bytes (n[XY]orus, depending on `flags')
* 0-(64+512*2) = 0-1088 bytes (depending on `n[XY]orus')
* 0-? (structure too complicated to be shown here; depending on
* `flags')
* 1-? glyph data (faintly resembling PS Type 1 charstrings)
*
* ==> minimum size 3 bytes
*
* compoundGps (size at most 2^16 bytes)
* 1 byte (nElements <= 63, flags)
* + 0-(1+255*(2+255)) = 0-65536 (depending on `flags')
* + nElements * (6-14 bytes)
*
* bitmapGps (size at most 2^16 bytes)
* 1 byte (flags)
* 3-13 bytes (position info, depending on `flags')
* 0-? bitmap data
*
* ==> minimum size 4 bytes
*
* PFR trailer
* 8 bytes
*
*
* ==> minimum size of a valid PFR:
* 58 (header)
* + 2 (nLogFonts)
* + 27 (1 physFontRecord)
* + 8 (trailer)
* -----
* 95 bytes
*
*/
/*************************************************************************/
/*************************************************************************/
/***** *****/
@ -212,6 +299,16 @@
FT_READ_USHORT( count ) )
goto Exit;
/* check maximum value and a rough minimum size */
if ( count > ( ( 1 << 16 ) - 2 ) / 5 ||
2 + count * 5 >= stream->size - section_offset )
{
FT_ERROR(( "pfr_log_font_count:"
" invalid number of logical fonts\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
result = count;
Exit:
@ -530,8 +627,6 @@
FT_Memory memory = phy_font->memory;
FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
if ( FT_NEW( item ) )
goto Exit;
@ -782,7 +877,7 @@
FT_Byte* q2;
PFR_CHECK( num_aux );
PFR_CHECK_SIZE( num_aux );
p += num_aux;
while ( num_aux > 0 )
@ -871,9 +966,6 @@
phy_font->num_chars = count = PFR_NEXT_USHORT( p );
phy_font->chars_offset = offset + (FT_Offset)( p - stream->cursor );
if ( FT_NEW_ARRAY( phy_font->chars, count ) )
goto Fail;
Size = 1 + 1 + 2;
if ( flags & PFR_PHY_2BYTE_CHARCODE )
Size += 1;
@ -890,7 +982,10 @@
if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
Size += 1;
PFR_CHECK( count * Size );
PFR_CHECK_SIZE( count * Size );
if ( FT_NEW_ARRAY( phy_font->chars, count ) )
goto Fail;
for ( n = 0; n < count; n++ )
{

View File

@ -25,14 +25,19 @@
FT_BEGIN_HEADER
/* some size checks should be always done (mainly to prevent */
/* excessive allocation for malformed data), ... */
#define PFR_CHECK_SIZE( x ) do \
{ \
if ( p + (x) > limit ) \
goto Too_Short; \
} while ( 0 )
/* ... and some only if intensive checking is explicitly requested */
#ifdef PFR_CONFIG_NO_CHECKS
#define PFR_CHECK( x ) do { } while ( 0 )
#else
#define PFR_CHECK( x ) do \
{ \
if ( p + (x) > limit ) \
goto Too_Short; \
} while ( 0 )
#define PFR_CHECK PFR_CHECK_SIZE
#endif
#define PFR_NEXT_BYTE( p ) FT_NEXT_BYTE( p )

View File

@ -510,8 +510,7 @@
break;
default:
FT_ERROR(( "pfr_read_bitmap_data: invalid image type\n" ));
error = FT_THROW( Invalid_File_Format );
;
}
}
@ -632,6 +631,53 @@
&xsize, &ysize,
&advance, &format );
/*
* Before allocating the target bitmap, we check whether the given
* bitmap dimensions are valid, depending on the image format.
*
* Format 0: We have a stream of pixels (with 8 pixels per byte).
*
* (xsize * ysize + 7) / 8 <= gps_size
*
* Format 1: Run-length encoding; the high nibble holds the number of
* white bits, the low nibble the number of black bits. In
* other words, a single byte can represent at most 15
* pixels.
*
* xsize * ysize <= 15 * gps_size
*
* Format 2: Run-length encoding; the high byte holds the number of
* white bits, the low byte the number of black bits. In
* other words, two bytes can represent at most 255 pixels.
*
* xsize * ysize <= 255 * (gps_size + 1) / 2
*/
switch ( format )
{
case 0:
if ( ( (FT_ULong)xsize * ysize + 7 ) / 8 > gps_size )
error = FT_THROW( Invalid_Table );
break;
case 1:
if ( (FT_ULong)xsize * ysize > 15 * gps_size )
error = FT_THROW( Invalid_Table );
break;
case 2:
if ( (FT_ULong)xsize * ysize > 255 * ( ( gps_size + 1 ) / 2 ) )
error = FT_THROW( Invalid_Table );
break;
default:
FT_ERROR(( "pfr_slot_load_bitmap: invalid image type\n" ));
error = FT_THROW( Invalid_Table );
}
if ( error )
{
if ( FT_ERR_EQ( error, Invalid_Table ) )
FT_ERROR(( "pfr_slot_load_bitmap: invalid bitmap dimensions\n" ));
goto Exit;
}
/*
* XXX: on 16bit systems we return an error for huge bitmaps
* that cause size truncation, because truncated