* 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..
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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
diff --git a/ChangeLog b/ChangeLog
index 325fabe..85fbd91 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2002-02-28 David Turner <david@freetype.org>
+
+ * 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 <david@freetype.org>
* renaming stream functions to the FT_Subject_Action scheme:
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index f84cc04..8dc5cdc 100644
--- 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,31 +1009,16 @@
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;
-
- /* 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;
- }
+ if (error)
+ goto Exit;
#ifdef FT_DEBUG_LEVEL_TRACE
@@ -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 */