shithub: freetype+ttf2subf

Download patch

ref: ab7e52b1c78b27d74e9555c6488c46bd62101804
parent: 15b60bb513984c5f0725d45b80e8798e21502dcf
author: David Turner <[email protected]>
date: Tue Mar 3 17:37:13 EST 2009

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.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2009-03-03  David Turner  <[email protected]>
 
+	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  <[email protected]>
+
 	Update documentation and bump version number to 2.3.9.
 
 	* include/freetype/freetype.h: Bump patch version to 9.
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -33,6 +33,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
 
--- 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,12 +184,15 @@
     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;
@@ -193,6 +199,7 @@
       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,6 +207,9 @@
 
       next = base + length;
 
+      if (next > p_limit)  /* handle broken table */
+        next = p_limit;
+
       if ( ( face->kern_avail_bits & mask ) == 0 )
         goto NextTable;
 
@@ -206,15 +216,18 @@
       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 */
           {