ref: 92359bd8851448ba40167affdf5663659a7b28f0
parent: 9ada669a2c443020f983d0876becdcea70d74da4
author: Werner Lemberg <[email protected]>
date: Sat Feb 7 04:47:23 EST 2015
[sfnt] Fix Savannah bug #44184. * src/sfnt/ttload.c (check_table_dir, tt_face_load_font_dir): No longer reject `htmx' and `vmtx' tables with invalid length but sanitize them.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2015-02-07 Werner Lemberg <[email protected]>
+
+ [sfnt] Fix Savannah bug #44184.
+
+ * src/sfnt/ttload.c (check_table_dir, tt_face_load_font_dir): No
+ longer reject `htmx' and `vmtx' tables with invalid length but
+ sanitize them.
+
2015-02-06 Jon Anderson <[email protected]>
[truetype] Fix regression in the incremental glyph loader.
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -208,12 +208,23 @@
/* we ignore invalid tables */
- /* table.Offset + table.Length > stream->size ? */
- if ( table.Length > stream->size ||
- table.Offset > stream->size - table.Length )
- {
- FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
+ if ( table.Offset > stream->size )
continue;
+ else if ( table.Length > stream->size - table.Offset )
+ {
+ /* Some tables have such a simple structure that clipping its */
+ /* contents is harmless. This also makes FreeType less sensitive */
+ /* to invalid table lengths (which programs like Acroread seem to */
+ /* ignore in general). */
+
+ if ( table.Tag == TTAG_hmtx ||
+ table.Tag == TTAG_vmtx )
+ valid_entries++;
+ else
+ {
+ FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
+ continue;
+ }
}
else
valid_entries++;
@@ -397,12 +408,36 @@
entry->Offset = FT_GET_ULONG();
entry->Length = FT_GET_ULONG();
- /* ignore invalid tables */
+ /* ignore invalid tables that can't be sanitized */
- /* entry->Offset + entry->Length > stream->size ? */
- if ( entry->Length > stream->size ||
- entry->Offset > stream->size - entry->Length )
+ if ( entry->Offset > stream->size )
continue;
+ else if ( entry->Length > stream->size - entry->Offset )
+ {
+ if ( entry->Tag == TTAG_hmtx ||
+ entry->Tag == TTAG_vmtx )
+ {
+ FT_ULong old_length = entry->Length;
+
+
+ /* make metrics table length a multiple of 4 */
+ entry->Length = ( stream->size - entry->Offset ) & ~3;
+
+ FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx"
+ " (sanitized; original length %08lx)\n",
+ (FT_Char)( entry->Tag >> 24 ),
+ (FT_Char)( entry->Tag >> 16 ),
+ (FT_Char)( entry->Tag >> 8 ),
+ (FT_Char)( entry->Tag ),
+ entry->Offset,
+ entry->Length,
+ entry->CheckSum,
+ old_length ));
+ entry++;
+ }
+ else
+ continue;
+ }
else
{
FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx\n",