From 0b5282f170e54f4e853b78910d24fd96edfa1d04 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Thu, 5 May 2005 07:44:20 +0000 Subject: [PATCH] Handle malformed `loca' table entries. * docs/TODO: Add some bugs which should be fixed. * include/freetype/internal/tttypes.h (TT_FaceRec): Add `glyf_len' element. * src/truetype/ttpload.c (tt_face_load_loca): Get length of `glyf' table. (tt_face_get_location): Fix computation of `asize' for malformed `loca' entries. --- ChangeLog | 33 ++++++++++++++++++------- include/freetype/internal/tttypes.h | 5 ++++ src/truetype/ttpload.c | 37 +++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index b61ff2c68..5f625550f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,15 +1,30 @@ +2005-05-05 Werner Lemberg + + Handle malformed `loca' table entries. + + * docs/TODO: Add some bugs which should be fixed. + + * include/freetype/internal/tttypes.h (TT_FaceRec): Add `glyf_len' + element. + + * src/truetype/ttpload.c (tt_face_load_loca): Get length of `glyf' + table. + (tt_face_get_location): Fix computation of `asize' for malformed + `loca' entries. + 2005-05-01 David Turner - * Jamfile: removing otvalid from the list of compiled modules - * include/freetype/internal/ftserv.h: added compiler pragmas to get rid - of annoying warnings with Visual C++ compiler in maximum warning mode - - * src/autofit/afhints.c, src/autofit/aflatin.c, src/base/ftstroke.c, - src/bdf/bdfdrivr.c, src/cache/ftcbasic.c, src/cache/ftccmap.c, - src/cache/ftcmanag.c, src/cff/cffload.c, src/cid/cidload.c, - src/lzw/zopen.c, src/otvalid/otvgdef.c, src/pcf/pcfread.c, - src/sfnt/sfobjs.c, src/truetype/ttgxvar.c: removing compiler warnings + * Jamfile: Remove `otvalid' from the list of compiled modules. + * include/freetype/internal/ftserv.h: Add compiler pragmas to get + rid of annoying warnings with Visual C++ compiler in maximum warning + mode. + + * src/autofit/afhints.c, src/autofit/aflatin.c, src/base/ftstroke.c, + src/bdf/bdfdrivr.c, src/cache/ftcbasic.c, src/cache/ftccmap.c, + src/cache/ftcmanag.c, src/cff/cffload.c, src/cid/cidload.c, + src/lzw/zopen.c, src/otvalid/otvgdef.c, src/pcf/pcfread.c, + src/sfnt/sfobjs.c, src/truetype/ttgxvar.c: Remove compiler warnings. 2005-04-28 Werner Lemberg diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h index 79e6e84db..7f8335f82 100644 --- a/include/freetype/internal/tttypes.h +++ b/include/freetype/internal/tttypes.h @@ -1136,6 +1136,9 @@ FT_BEGIN_HEADER /* glyph data within the `glyf' table. */ /* Ignored for Type 2 font faces. */ /* */ + /* glyf_len :: The length of the `glyf' table. Needed */ + /* for malformed `loca' tables. */ + /* */ /* font_program_size :: Size in bytecodes of the face's font */ /* program. 0 if none defined. Ignored for */ /* Type 2 fonts. */ @@ -1298,6 +1301,8 @@ FT_BEGIN_HEADER FT_Long* glyph_locations; #endif + FT_ULong glyf_len; + /* the font program, if any */ FT_ULong font_program_size; FT_Byte* font_program; diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c index ee7479a1e..2f589b471 100644 --- a/src/truetype/ttpload.c +++ b/src/truetype/ttpload.c @@ -68,6 +68,11 @@ FT_ULong table_len; + /* we need the size of the `glyf' table for malformed `loca' tables */ + error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len ); + if ( error ) + goto Exit; + FT_TRACE2(( "Locations " )); error = face->goto_table( face, TTAG_loca, stream, &table_len ); if ( error ) @@ -152,7 +157,16 @@ } } - *asize = (FT_UInt)( pos2 - pos1 ); + /* It isn't mentioned explicitly that the `loca' table must be */ + /* ordered, but implicitly it refers to the length of an entry */ + /* as the difference between the current and the next position. */ + /* Anyway, there do exist (malformed) fonts which don't obey */ + /* this rule, so we are only able to provide an upper bound for */ + /* the size. */ + if ( pos2 > pos1 ) + *asize = (FT_UInt)( pos2 - pos1 ); + else + *asize = (FT_UInt)( face->glyf_len - pos1 ); return pos1; } @@ -182,6 +196,11 @@ FT_ULong table_len; + /* we need the size of the `glyf' table for malformed `loca' tables */ + error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len ); + if ( error ) + goto Exit; + FT_TRACE2(( "Locations " )); LongOffsets = face->header.Index_To_Loc_Format; @@ -259,7 +278,21 @@ count = 0; if ( gindex < (FT_UInt)face->num_locations - 1 ) - count = (FT_UInt)( face->glyph_locations[gindex + 1] - offset ); + { + FT_ULong offset1 = face->glyph_locations[gindex + 1]; + + + /* It isn't mentioned explicitly that the `loca' table must be */ + /* ordered, but implicitly it refers to the length of an entry */ + /* as the difference between the current and the next position. */ + /* Anyway, there do exist (malformed) fonts which don't obey */ + /* this rule, so we are only able to provide an upper bound for */ + /* the size. */ + if ( offset1 > offset ) + count = (FT_UInt)( offset1 - offset ); + else + count = (FT_UInt)( face->glyf_len - offset ); + } *asize = count; return offset;