Commit 643d49df0919b56c6603ab9310839899b77aad8a

suzuki toshiya 2010-09-20T01:07:57

[truetype] Sanitize the broken offsets in `loca'. * src/truetype/ttpload.c (tt_face_get_location): If `pos1', the offset to the requested entry in `glyf' exceeds the end of the table, return offset=0, length=0. If `pos2', the offset to the next entry in `glyf' exceeds the end of the table, truncate the entry length at the end of `glyf' table. See Savannah bug #31040.

diff --git a/ChangeLog b/ChangeLog
index 7c5f017..2031ae9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2010-09-19  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
 
+	[truetype] Sanitize the broken offsets in `loca'.
+
+	* src/truetype/ttpload.c (tt_face_get_location): If `pos1', the
+	offset to the requested entry in `glyf' exceeds the end of the
+	table, return offset=0, length=0.  If `pos2', the offset to the
+	next entry in `glyf' exceeds the end of the table, truncate
+	the entry length at the end of `glyf' table.
+	See Savannah bug #31040.
+
+2010-09-19  suzuki toshiya  <mpsuzuki@hiroshima-u.ac.jp>
+
 	[sfnt] Prevent overrunning in `post' table parser.
 
 	* src/sfnt/ttpost.c (load_post_names): Get the length of
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index a311b03..c531733 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -203,6 +203,26 @@
       }
     }
 
+    /* Check broken location data */
+    if ( pos1 >= face->glyf_len )
+    {
+      FT_TRACE1(( "tt_face_get_location:"
+                 " too large offset=0x%08lx found for gid=0x%04lx,"
+                 " exceeding the end of glyf table (0x%08lx)\n",
+                 pos1, gindex, face->glyf_len ));
+      *asize = 0;
+      return 0;
+    }
+
+    if ( pos2 >= face->glyf_len )
+    {
+      FT_TRACE1(( "tt_face_get_location:"
+                 " too large offset=0x%08lx found for gid=0x%04lx,"
+                 " truncate at the end of glyf table (0x%08lx)\n",
+                 pos2, gindex + 1, face->glyf_len ));
+      pos2 = face->glyf_len;
+    }
+
     /* The `loca' table must be ordered; it refers to the length of */
     /* an entry as the difference between the current and the next  */
     /* position.  However, there do exist (malformed) fonts which   */