diff --git a/ChangeLog b/ChangeLog index 92b5b9b76..c120afd5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2015-09-21 suzuki toshiya + + [base] Check too long POST and sfnt resource (#45919). + + * src/base/ftbase.h (FT_MAC_RFORK_MAX_LEN): Maximum length + of the resource fork for Mac OS. The resource fork larger + than 16 MB can be written but could not be handled + correctly, at least in Carbon routine. + See https://support.microsoft.com/en-us/kb/130437 + + * src/base/ftobjs.c (Mac_Read_POST_Resource): No need `0x' + for `%p' formatter. + + * src/base/ftbase.c (Mac_Read_POST_Resource): Check the + fragment and total size of the concatenated POST resource + before buffer allocation. + (Mac_Read_sfnt_Resource): Check the declared size of + sfnt resource before buffer allocation. + + * src/base/ftmac.c (read_lwfn, FT_New_Face_From_SFNT): + Check the total resource size before buffer allocation. + 2015-09-19 Werner Lemberg [sfnt] Improve handling of invalid SFNT table entries (#45987). diff --git a/src/base/ftbase.h b/src/base/ftbase.h index cb57f9686..0bd9e65ef 100644 --- a/src/base/ftbase.h +++ b/src/base/ftbase.h @@ -27,6 +27,11 @@ FT_BEGIN_HEADER +/* MacOS resource fork cannot exceed 16 MB at least for Carbon code */ +/* see https://support.microsoft.com/en-us/kb/130437 */ +#define FT_MAC_RFORK_MAX_LEN 0x00FFFFFFUL + + /* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */ /* font, and try to load a face specified by the face_index. */ FT_LOCAL( FT_Error ) diff --git a/src/base/ftmac.c b/src/base/ftmac.c index 446a23a75..846319045 100644 --- a/src/base/ftmac.c +++ b/src/base/ftmac.c @@ -621,8 +621,8 @@ total_size += GetHandleSize( post_data ) - 2; last_code = code; - /* detect integer overflows */ - if ( total_size < old_total_size ) + /* detect resource fork overflow */ + if ( FT_MAC_RFORK_MAX_LEN < total_size ) { error = FT_THROW( Array_Too_Large ); goto Error; @@ -747,6 +747,11 @@ return FT_THROW( Invalid_Handle ); sfnt_size = (FT_ULong)GetHandleSize( sfnt ); + + /* detect resource fork overflow */ + if ( FT_MAC_RFORK_MAX_LEN < sfnt_size ) + return FT_THROW( Array_Too_Large ); + if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) ) { ReleaseResource( sfnt ); diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 3a41ac00a..b465a45c9 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -1586,12 +1586,14 @@ /* FT2 allocator takes signed long buffer length, * too large value causing overflow should be checked */ - FT_TRACE4(( " POST fragment #%d: length=0x%08x\n", - i, temp)); - if ( 0x7FFFFFFFUL < temp || pfb_len + temp + 6 < pfb_len ) + FT_TRACE4(( " POST fragment #%d: length=0x%08x" + " total pfb_len=0x%08x\n", + i, temp, pfb_len + temp + 6)); + if ( FT_MAC_RFORK_MAX_LEN < temp || + FT_MAC_RFORK_MAX_LEN - temp < pfb_len + 6 ) { - FT_TRACE2(( " too long fragment length makes" - " pfb_len confused: temp=0x%08x\n", temp )); + FT_TRACE2(( " MacOS resource length cannot exceed" + " 0x%08x\n", FT_MAC_RFORK_MAX_LEN )); error = FT_THROW( Invalid_Offset ); goto Exit; } @@ -1664,7 +1666,7 @@ else { FT_TRACE3(( " Write POST fragment #%d header (4-byte) to buffer" - " 0x%p + 0x%08x\n", i, pfb_data, pfb_lenpos )); + " %p + 0x%08x\n", i, pfb_data, pfb_lenpos )); if ( pfb_lenpos + 3 > pfb_len + 2 ) goto Exit2; pfb_data[pfb_lenpos ] = (FT_Byte)( len ); @@ -1676,7 +1678,7 @@ break; FT_TRACE3(( " Write POST fragment #%d header (6-byte) to buffer" - " 0x%p + 0x%08x\n", i, pfb_data, pfb_pos )); + " %p + 0x%08x\n", i, pfb_data, pfb_pos )); if ( pfb_pos + 6 > pfb_len + 2 ) goto Exit2; pfb_data[pfb_pos++] = 0x80; @@ -1696,7 +1698,7 @@ goto Exit2; FT_TRACE3(( " Load POST fragment #%d (%d byte) to buffer" - " 0x%p + 0x%08x\n", i, rlen, pfb_data, pfb_pos )); + " %p + 0x%08x\n", i, rlen, pfb_data, pfb_pos )); error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen ); if ( error ) goto Exit2; @@ -1774,6 +1776,8 @@ goto Exit; if ( rlen == -1 ) return FT_THROW( Cannot_Open_Resource ); + if ( rlen > FT_MAC_RFORK_MAX_LEN ) + return FT_THROW( Invalid_Offset ); error = open_face_PS_from_sfnt_stream( library, stream,