[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:
parent
4a3fce93c2
commit
fba29fabb3
18
ChangeLog
18
ChangeLog
|
@ -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).
|
||||
|
|
|
@ -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++ )
|
||||
{
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue