shithub: freetype+ttf2subf

Download patch

ref: c03d9cf5cde857a28773cb0b287875f7342bfdc7
parent: 617a2e1c3c8176e8ae31313a784829f278b1766e
author: David Turner <[email protected]>
date: Wed Feb 27 18:10:19 EST 2002

* src/sfnt/ttload.c (TT_Load_Names): simplifying and securing the
        names table loader. Invalid individual name entries are now handled
        correctly. This allows the loading of very buggy fonts like
        "foxjump.ttf" without allocating tons of memory and causing crashes..

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2002-02-28  David Turner   <[email protected]>
+
+        * src/sfnt/ttload.c (TT_Load_Names): simplifying and securing the
+        names table loader. Invalid individual name entries are now handled
+        correctly. This allows the loading of very buggy fonts like
+        "foxjump.ttf" without allocating tons of memory and causing crashes..
+
+        * src/otlayout/otlcommon.h, src/otlayout/otlcommon.c: adding (still
+        experimental) code for OpenType Layout tables validation and parsing
+
+        * src/type1/t1cmap.h, src/type1/t1cmap.c: adding (still experimental)
+        code for Type 1 charmap processing
+
+        * src/sfnt/ttcmap0.c: completing the experimental SFNT charmap
+        processing
+
+        * include/freetype/internal/ftobjs.h: adding validation support as
+        well as internal charmap object definitions (FT_CMap != FT_CharMap)
+
 2002-02-24  David Turner   <[email protected]>
 
         * renaming stream functions to the FT_Subject_Action scheme:
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -923,7 +923,8 @@
     FT_Memory  memory = stream->memory;
 
     FT_ULong   table_pos, table_len;
-    FT_ULong   storageSize;
+    FT_ULong   storageOffset, storageSize;
+    FT_Byte*   storage;
 
     TT_NameTable*  names;
 
@@ -973,13 +974,26 @@
     if ( READ_Fields( name_table_fields, names ) )
       goto Exit;
 
+    /* check the 'storageOffset' field */
+    storageOffset = names->storageOffset;
+    if ( storageOffset <  (FT_ULong)(6 + 12*names->numNameRecords) ||
+         table_len     <= storageOffset                            )
+    {
+      FT_ERROR(( "TT.load_names: invalid 'name' table\n" ));
+      error = SFNT_Err_Name_Table_Missing;
+      goto Exit;
+    }
+
+    storageSize = (FT_ULong)(table_len - storageOffset);
+
     /* Allocate the array of name records. */
-    if ( ALLOC_ARRAY( names->names,
-                      names->numNameRecords,
-                      TT_NameRec )                   ||
+    if ( ALLOC( names->names,
+                names->numNameRecords*sizeof(TT_NameRec) + storageSize )  ||
          ACCESS_Frame( names->numNameRecords * 12L ) )
       goto Exit;
 
+    storage = (FT_Byte*)(names->names + names->numNameRecords);
+
     /* Load the name records and determine how much storage is needed */
     /* to hold the strings themselves.                                */
     {
@@ -987,8 +1001,6 @@
       TT_NameRec*  limit = cur + names->numNameRecords;
 
 
-      storageSize = 0;
-
       for ( ; cur < limit; cur ++ )
       {
         FT_ULong  upper;
@@ -997,32 +1009,17 @@
         if ( READ_Fields( name_record_fields, cur ) )
           break;
 
-        upper = (FT_ULong)( cur->stringOffset + cur->stringLength );
-        if ( upper > storageSize )
-          storageSize = upper;
+        /* invalid name entries will have "cur->string" set to NULL !! */
+        if ( (FT_ULong)(cur->stringOffset + cur->stringLength) < storageSize )
+          cur->string = storage + cur->stringOffset;
       }
     }
 
     FORGET_Frame();
 
-    if ( storageSize > 0 )
-    {
-      /* allocate the name storage area in memory, then read it */
-      if ( ALLOC( names->storage, storageSize )               ||
-           FILE_Read_At( table_pos + names->storageOffset,
-                         names->storage, storageSize ) )
-        goto Exit;
+    if (error)
+      goto Exit;
 
-      /* Go through and assign the string pointers to the name records. */
-      {
-        TT_NameRec*  cur   = names->names;
-        TT_NameRec*  limit = cur + names->numNameRecords;
-
-
-        for ( ; cur < limit; cur++ )
-          cur->string = names->storage + cur->stringOffset;
-      }
-
 #ifdef FT_DEBUG_LEVEL_TRACE
 
       /* Print Name Record Table in case of debugging */
@@ -1036,7 +1033,7 @@
           FT_UInt  j;
 
 
-          FT_TRACE3(( "%d %d %x %d\n  ",
+          FT_TRACE3(( "(%2d %2d %4x %2d)  ",
                        cur->platformID,
                        cur->encodingID,
                        cur->languageID,
@@ -1047,19 +1044,21 @@
           if ( cur->string )
             for ( j = 0; j < (FT_UInt)cur->stringLength; j++ )
             {
-              FT_Char  c = *( cur->string + j );
+              FT_Byte  c = *(FT_Byte*)(cur->string + j);
 
 
-              if ( (FT_Byte)c < 128 )
+              if ( c >= 32 && c < 128 )
                 FT_TRACE3(( "%c", c ));
             }
+          else
+            FT_TRACE3(( "INVALID ENTRY !!\n" ));
+
+          FT_TRACE3(( "\n" ));
         }
       }
-      FT_TRACE3(( "\n" ));
 
 #endif /* FT_DEBUG_LEVEL_TRACE */
 
-    }
     FT_TRACE2(( "loaded\n" ));
 
     /* everything went well, update face->num_names */