Commit 5452fbe39dc3702962d9b448d87ae9909f7fb867

Werner Lemberg 2005-05-05T07:44:20

Handle malformed `loca' table entries. * docs/TODO: Add some bugs which should be fixed. * include/freetype/internal/tttypes.h (TT_FaceRec): Add `glyf_len' element. * src/truetype/ttpload.c (tt_face_load_loca): Get length of `glyf' table. (tt_face_get_location): Fix computation of `asize' for malformed `loca' entries.

diff --git a/ChangeLog b/ChangeLog
index b61ff2c..5f62555 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,15 +1,30 @@
+2005-05-05  Werner Lemberg  <wl@gnu.org>
+
+	Handle malformed `loca' table entries.
+
+	* docs/TODO: Add some bugs which should be fixed.
+
+	* include/freetype/internal/tttypes.h (TT_FaceRec): Add `glyf_len'
+	element.
+
+	* src/truetype/ttpload.c (tt_face_load_loca): Get length of `glyf'
+	table.
+	(tt_face_get_location): Fix computation of `asize' for malformed
+	`loca' entries.
+
 2005-05-01  David Turner  <david@freetype.org>
 
-  * Jamfile: removing otvalid from the list of compiled modules
-  * include/freetype/internal/ftserv.h: added compiler pragmas to get rid
-    of annoying warnings with Visual C++ compiler in maximum warning mode
-    
-  * src/autofit/afhints.c, src/autofit/aflatin.c, src/base/ftstroke.c,
-    src/bdf/bdfdrivr.c, src/cache/ftcbasic.c, src/cache/ftccmap.c,
-    src/cache/ftcmanag.c, src/cff/cffload.c, src/cid/cidload.c,
-    src/lzw/zopen.c, src/otvalid/otvgdef.c, src/pcf/pcfread.c,
-    src/sfnt/sfobjs.c, src/truetype/ttgxvar.c: removing compiler warnings
+	* Jamfile: Remove `otvalid' from the list of compiled modules.
 
+	* include/freetype/internal/ftserv.h: Add compiler pragmas to get
+	rid of annoying warnings with Visual C++ compiler in maximum warning
+	mode.
+    
+	* src/autofit/afhints.c, src/autofit/aflatin.c, src/base/ftstroke.c,
+	src/bdf/bdfdrivr.c, src/cache/ftcbasic.c, src/cache/ftccmap.c,
+	src/cache/ftcmanag.c, src/cff/cffload.c, src/cid/cidload.c,
+	src/lzw/zopen.c, src/otvalid/otvgdef.c, src/pcf/pcfread.c,
+	src/sfnt/sfobjs.c, src/truetype/ttgxvar.c: Remove compiler warnings.
 
 2005-04-28  Werner Lemberg  <wl@gnu.org>
 
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index 79e6e84..7f8335f 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -1136,6 +1136,9 @@ FT_BEGIN_HEADER
   /*                            glyph data within the `glyf' table.        */
   /*                            Ignored for Type 2 font faces.             */
   /*                                                                       */
+  /*    glyf_len             :: The length of the `glyf' table.  Needed    */
+  /*                            for malformed `loca' tables.               */
+  /*                                                                       */
   /*    font_program_size    :: Size in bytecodes of the face's font       */
   /*                            program.  0 if none defined.  Ignored for  */
   /*                            Type 2 fonts.                              */
@@ -1298,6 +1301,8 @@ FT_BEGIN_HEADER
     FT_Long*              glyph_locations;
 #endif
 
+    FT_ULong              glyf_len;
+
     /* the font program, if any */
     FT_ULong              font_program_size;
     FT_Byte*              font_program;
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index ee7479a..2f589b4 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -68,6 +68,11 @@
     FT_ULong  table_len;
 
 
+    /* we need the size of the `glyf' table for malformed `loca' tables */
+    error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
+    if ( error )
+      goto Exit;
+
     FT_TRACE2(( "Locations " ));
     error = face->goto_table( face, TTAG_loca, stream, &table_len );
     if ( error )
@@ -152,7 +157,16 @@
       }
     }
 
-    *asize = (FT_UInt)( pos2 - pos1 );
+    /* It isn't mentioned explicitly that the `loca' table must be  */
+    /* ordered, but implicitly it refers to the length of an entry  */
+    /* as the difference between the current and the next position. */
+    /* Anyway, there do exist (malformed) fonts which don't obey    */
+    /* this rule, so we are only able to provide an upper bound for */
+    /* the size.                                                    */
+    if ( pos2 > pos1 )
+      *asize = (FT_UInt)( pos2 - pos1 );
+    else
+      *asize = (FT_UInt)( face->glyf_len - pos1 );
 
     return pos1;
   }
@@ -182,6 +196,11 @@
     FT_ULong   table_len;
 
 
+    /* we need the size of the `glyf' table for malformed `loca' tables */
+    error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
+    if ( error )
+      goto Exit;
+
     FT_TRACE2(( "Locations " ));
     LongOffsets = face->header.Index_To_Loc_Format;
 
@@ -259,7 +278,21 @@
     count  = 0;
 
     if ( gindex < (FT_UInt)face->num_locations - 1 )
-      count = (FT_UInt)( face->glyph_locations[gindex + 1] - offset );
+    {
+      FT_ULong  offset1 = face->glyph_locations[gindex + 1];
+
+
+      /* It isn't mentioned explicitly that the `loca' table must be  */
+      /* ordered, but implicitly it refers to the length of an entry  */
+      /* as the difference between the current and the next position. */
+      /* Anyway, there do exist (malformed) fonts which don't obey    */
+      /* this rule, so we are only able to provide an upper bound for */
+      /* the size.                                                    */
+      if ( offset1 > offset )
+        count = (FT_UInt)( offset1 - offset );
+      else
+        count = (FT_UInt)( face->glyf_len - offset );
+    }
 
     *asize = count;
     return offset;