From 92359bd8851448ba40167affdf5663659a7b28f0 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Sat, 7 Feb 2015 09:47:23 +0100 Subject: [PATCH] [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. --- ChangeLog | 8 +++++++ src/sfnt/ttload.c | 53 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7828f2064..78119aaf4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2015-02-07 Werner Lemberg + + [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 [truetype] Fix regression in the incremental glyph loader. diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c index 8606e85ca..8b1f2d0d5 100644 --- 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",