diff --git a/ChangeLog b/ChangeLog index 9f7fe9a25..95833b90c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-03-03 David Turner + + Fix SFNT kerning table parser against malformed tables. + Closes Savannah BUG #25750 + + * src/sfnt/ttkern.c (tt_face_get_kerning): fix a bug + where a malformed table would be succesfully loaded but + later crash the engine during parsing. + 2009-03-03 David Turner Update documentation and bump version number to 2.3.9. diff --git a/docs/CHANGES b/docs/CHANGES index e7eebf789..83e57c7be 100644 --- a/docs/CHANGES +++ b/docs/CHANGES @@ -33,6 +33,8 @@ CHANGES BETWEEN 2.3.9 and 2.3.8 - `FT_Get_Advance' (and `FT_Get_Advances') returned bad values for almost all font formats except TrueType fonts. + - Fix a bug in the SFNT kerning table loader/parser which could crash + the engine if certain malformed tables were encountered. II. IMPORTANT CHANGES diff --git a/src/sfnt/ttkern.c b/src/sfnt/ttkern.c index 28e52c333..52f957410 100644 --- a/src/sfnt/ttkern.c +++ b/src/sfnt/ttkern.c @@ -103,6 +103,9 @@ p_next += length; + if (p_next > p_limit) /* handle broken table */ + p_next = p_limit; + /* only use horizontal kerning tables */ if ( ( coverage & ~8 ) != 0x0001 || p + 8 > p_limit ) @@ -111,8 +114,8 @@ num_pairs = FT_NEXT_USHORT( p ); p += 6; - if ( p + 6 * num_pairs > p_limit ) - goto NextTable; + if ( (p_next - p)/6 < (int)num_pairs ) /* handle broken count */ + num_pairs = (FT_UInt)((p_next - p)/6); avail |= mask; @@ -181,18 +184,22 @@ FT_Int result = 0; FT_UInt count, mask = 1; FT_Byte* p = face->kern_table; + FT_Byte* p_limit = p + face->kern_table_size; p += 4; mask = 0x0001; - for ( count = face->num_kern_tables; count > 0; count--, mask <<= 1 ) + for ( count = face->num_kern_tables; + count > 0 && p + 6 <= p_limit; + count--, mask <<= 1 ) { FT_Byte* base = p; FT_Byte* next = base; FT_UInt version = FT_NEXT_USHORT( p ); FT_UInt length = FT_NEXT_USHORT( p ); FT_UInt coverage = FT_NEXT_USHORT( p ); + FT_UInt num_pairs; FT_Int value = 0; FT_UNUSED( version ); @@ -200,22 +207,28 @@ next = base + length; + if (next > p_limit) /* handle broken table */ + next = p_limit; + if ( ( face->kern_avail_bits & mask ) == 0 ) goto NextTable; if ( p + 8 > next ) goto NextTable; + num_pairs = FT_NEXT_USHORT( p ); + p += 6; + + if ((next - p)/6 < (int)num_pairs) /* handle broken count */ + num_pairs = (FT_UInt)((next - p)/6); + switch ( coverage >> 8 ) { case 0: { - FT_UInt num_pairs = FT_NEXT_USHORT( p ); - FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph ); + FT_ULong key0 = TT_KERN_INDEX( left_glyph, right_glyph ); - p += 6; - if ( face->kern_order_bits & mask ) /* binary search */ { FT_UInt min = 0;