diff options
Diffstat (limited to 'src/truetype/ttpload.c')
-rw-r--r-- | src/truetype/ttpload.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c index a311b03..818b29d 100644 --- a/src/truetype/ttpload.c +++ b/src/truetype/ttpload.c @@ -4,7 +4,7 @@ /* */ /* TrueType-specific tables loader (body). */ /* */ -/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 by */ +/* Copyright 1996-2002, 2004-2011 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -110,15 +110,16 @@ face->num_locations = table_len >> shift; } - if ( face->num_locations != (FT_ULong)face->root.num_glyphs ) + if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 ) { FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n", - face->num_locations, face->root.num_glyphs )); + face->num_locations - 1, face->root.num_glyphs )); /* we only handle the case where `maxp' gives a larger value */ - if ( face->num_locations < (FT_ULong)face->root.num_glyphs ) + if ( face->num_locations <= (FT_ULong)face->root.num_glyphs ) { - FT_Long new_loca_len = (FT_Long)face->root.num_glyphs << shift; + FT_Long new_loca_len = + ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift; TT_Table entry = face->dir_tables; TT_Table limit = entry + face->num_tables; @@ -137,9 +138,15 @@ dist = diff; } + if ( entry == limit ) + { + /* `loca' is the last table */ + dist = stream->size - pos; + } + if ( new_loca_len <= dist ) { - face->num_locations = face->root.num_glyphs; + face->num_locations = face->root.num_glyphs + 1; table_len = new_loca_len; FT_TRACE2(( "adjusting num_locations to %d\n", @@ -203,6 +210,26 @@ } } + /* Check broken location data */ + if ( pos1 >= face->glyf_len ) + { + FT_TRACE1(( "tt_face_get_location:" + " too large offset=0x%08lx found for gid=0x%04lx," + " exceeding the end of glyf table (0x%08lx)\n", + pos1, gindex, face->glyf_len )); + *asize = 0; + return 0; + } + + if ( pos2 >= face->glyf_len ) + { + FT_TRACE1(( "tt_face_get_location:" + " too large offset=0x%08lx found for gid=0x%04lx," + " truncate at the end of glyf table (0x%08lx)\n", + pos2, gindex + 1, face->glyf_len )); + pos2 = face->glyf_len; + } + /* The `loca' table must be ordered; it refers to the length of */ /* an entry as the difference between the current and the next */ /* position. However, there do exist (malformed) fonts which */ @@ -287,7 +314,7 @@ FT_Short* limit = cur + face->cvt_size; - for ( ; cur < limit; cur++ ) + for ( ; cur < limit; cur++ ) *cur = FT_GET_SHORT(); } |