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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
diff --git a/ChangeLog b/ChangeLog
index 9f7fe9a..95833b9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2009-03-03 David Turner <david@freetype.org>
+ 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 <david@freetype.org>
+
Update documentation and bump version number to 2.3.9.
* include/freetype/freetype.h: Bump patch version to 9.
diff --git a/docs/CHANGES b/docs/CHANGES
index e7eebf7..83e57c7 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 28e52c3..52f9574 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,21 +207,27 @@
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 */
{