From 913a36509099640dcbf5ace70b220d05eaa7b5c7 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Sun, 19 Nov 2006 09:19:17 +0000 Subject: [PATCH] Because FT_Load_Glyph expects CID values for CID-keyed fonts, the test for a valid glyph index must be deferred to the font drivers. This patch fixes Savannah bug #18301. * src/base/ftobjs.c (FT_Load_Glyph): Don't check `glyph_index'. * src/bdf/bdfdrivr.c (BDF_Glyph_Load), src/cff/cffgload.c (cff_slot_load), src/cid/cidgload.c (cid_slot_load_glyph), src/pcf/pcfdrivr.c (PCF_Glyph_Load), src/pfr/pfrobjs.c (pfr_slot_load), src/truetype/ttdriver.c (Load_Glyph), src/type1/t1gload.c (T1_Load_Glyph), src/winfonts/winfnt.c (FNT_Load_Glyph): Check validity of `glyph_index'. --- ChangeLog | 14 ++++++++++++++ src/base/ftcalc.c | 21 +++++++++++++++++++-- src/base/ftobjs.c | 4 ++-- src/bdf/bdfdrivr.c | 13 +++++++------ src/cff/cffgload.c | 26 ++++++++++++++------------ src/cff/cffload.c | 3 ++- src/cid/cidgload.c | 6 ++++++ src/pcf/pcfdrivr.c | 2 +- src/pfr/pfrobjs.c | 7 +++++-- src/truetype/ttdriver.c | 4 ++++ src/type1/t1gload.c | 6 ++++++ src/winfonts/winfnt.c | 3 ++- 12 files changed, 82 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index c8aef2c09..37be0cbf9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2006-11-18 Werner Lemberg + + Because FT_Load_Glyph expects CID values for CID-keyed fonts, the + test for a valid glyph index must be deferred to the font drivers. + This patch fixes Savannah bug #18301. + + * src/base/ftobjs.c (FT_Load_Glyph): Don't check `glyph_index'. + * src/bdf/bdfdrivr.c (BDF_Glyph_Load), src/cff/cffgload.c + (cff_slot_load), src/cid/cidgload.c (cid_slot_load_glyph), + src/pcf/pcfdrivr.c (PCF_Glyph_Load), src/pfr/pfrobjs.c + (pfr_slot_load), src/truetype/ttdriver.c (Load_Glyph), + src/type1/t1gload.c (T1_Load_Glyph), src/winfonts/winfnt.c + (FNT_Load_Glyph): Check validity of `glyph_index'. + 2006-11-13 David Turner * src/truetype/ttinterp.c (FIX_BYTECODE): Undefine. The interpreter diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c index 95db2796f..b7fb78199 100644 --- a/src/base/ftcalc.c +++ b/src/base/ftcalc.c @@ -315,6 +315,23 @@ /* documentation is in freetype.h */ + /* The FT_MulDiv function has been optimized thanks to ideas from */ + /* Graham Asher. The trick is to optimize computation when everything */ + /* fits within 32-bits (a rather common case). */ + /* */ + /* we compute 'a*b+c/2', then divide it by 'c'. (positive values) */ + /* */ + /* 46340 is FLOOR(SQRT(2^31-1)). */ + /* */ + /* if ( a <= 46340 && b <= 46340 ) then ( a*b <= 0x7FFEA810 ) */ + /* */ + /* 0x7FFFFFFF - 0x7FFEA810 = 0x157F0 */ + /* */ + /* if ( c < 0x157F0*2 ) then ( a*b+c/2 <= 0x7FFFFFFF ) */ + /* */ + /* and 2*0x157F0 = 176096 */ + /* */ + FT_EXPORT_DEF( FT_Long ) FT_MulDiv( FT_Long a, FT_Long b, @@ -551,7 +568,7 @@ /* apparently, the second version of this code is not compiled correctly */ - /* on Mac machines with the MPW C compiler.. tsk, tsk, tsk... */ + /* on Mac machines with the MPW C compiler.. tsk, tsk, tsk... */ #if 1 @@ -588,7 +605,7 @@ if ( r >= (FT_UInt32)y ) /* we know y is to be treated as unsigned here */ return ( s < 0 ? 0x80000001UL : 0x7FFFFFFFUL ); /* Return Max/Min Int32 if division overflow. */ - /* This includes division by zero! */ + /* This includes division by zero! */ q = 0; for ( i = 0; i < 32; i++ ) { diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 417dc704c..6a26140f7 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -549,8 +549,8 @@ if ( !face || !face->size || !face->glyph ) return FT_Err_Invalid_Face_Handle; - if ( glyph_index >= (FT_UInt)face->num_glyphs ) - return FT_Err_Invalid_Argument; + /* The validity test for `glyph_index' is performed by the */ + /* font drivers. */ slot = face->glyph; ft_glyphslot_clear( slot ); diff --git a/src/bdf/bdfdrivr.c b/src/bdf/bdfdrivr.c index c7939e31d..34071481b 100644 --- a/src/bdf/bdfdrivr.c +++ b/src/bdf/bdfdrivr.c @@ -648,16 +648,17 @@ THE SOFTWARE. FT_UInt glyph_index, FT_Int32 load_flags ) { - BDF_Face face = (BDF_Face)FT_SIZE_FACE( size ); + BDF_Face bdf = (BDF_Face)FT_SIZE_FACE( size ); + FT_Face face = FT_FACE( bdf ); FT_Error error = BDF_Err_Ok; FT_Bitmap* bitmap = &slot->bitmap; bdf_glyph_t glyph; - int bpp = face->bdffont->bpp; + int bpp = bdf->bdffont->bpp; FT_UNUSED( load_flags ); - if ( !face ) + if ( !face || glyph_index >= (FT_UInt)face->num_glyphs ) { error = BDF_Err_Invalid_Argument; goto Exit; @@ -665,12 +666,12 @@ THE SOFTWARE. /* index 0 is the undefined glyph */ if ( glyph_index == 0 ) - glyph_index = face->default_glyph; + glyph_index = bdf->default_glyph; else glyph_index--; /* slot, bitmap => freetype, glyph => bdflib */ - glyph = face->bdffont->glyphs[glyph_index]; + glyph = bdf->bdffont->glyphs[glyph_index]; bitmap->rows = glyph.bbx.height; bitmap->width = glyph.bbx.width; @@ -712,7 +713,7 @@ THE SOFTWARE. * used here, provided such fonts do exist. */ ft_synthesize_vertical_metrics( &slot->metrics, - face->bdffont->bbx.height << 6 ); + bdf->bdffont->bbx.height << 6 ); Exit: return error; diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c index 673a814d7..ca6bb0fc8 100644 --- a/src/cff/cffgload.c +++ b/src/cff/cffgload.c @@ -2285,6 +2285,20 @@ FT_Vector font_offset; + /* in a CID-keyed font, consider `glyph_index' as a CID and map */ + /* it immediately to the real glyph_index -- if it isn't a */ + /* subsetted font, glyph_indices and CIDs are identical, though */ + if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && + cff->charset.cids ) + { + if ( glyph_index < cff->charset.max_cid ) + glyph_index = cff->charset.cids[glyph_index]; + else + return CFF_Err_Invalid_Argument; + } + else if ( glyph_index >= cff->num_glyphs ) + return CFF_Err_Invalid_Argument; + if ( load_flags & FT_LOAD_NO_RECURSE ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; @@ -2376,18 +2390,6 @@ FT_ULong charstring_len; - /* in a CID-keyed font, consider `glyph_index' as a CID and map */ - /* it immediately to the real glyph_index -- if it isn't a */ - /* subsetted font, glyph_indices and CIDs are identical, though */ - if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && - cff->charset.cids ) - { - if ( glyph_index < cff->charset.max_cid ) - glyph_index = cff->charset.cids[glyph_index]; - else - glyph_index = 0; - } - cff_decoder_init( &decoder, face, size, glyph, hinting, FT_LOAD_TARGET_MODE( load_flags ) ); diff --git a/src/cff/cffload.c b/src/cff/cffload.c index cd88788b1..0c7025a59 100644 --- a/src/cff/cffload.c +++ b/src/cff/cffload.c @@ -1946,7 +1946,8 @@ encoding->count = 0; - error = cff_charset_compute_cids( charset, num_glyphs, stream->memory ); + error = cff_charset_compute_cids( charset, num_glyphs, + stream->memory ); if ( error ) goto Exit; diff --git a/src/cid/cidgload.c b/src/cid/cidgload.c index 68bd14e0f..aec34855c 100644 --- a/src/cid/cidgload.c +++ b/src/cid/cidgload.c @@ -275,6 +275,12 @@ FT_Vector font_offset; + if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) + { + error = CID_Err_Invalid_Argument; + goto Exit; + } + if ( load_flags & FT_LOAD_NO_RECURSE ) load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; diff --git a/src/pcf/pcfdrivr.c b/src/pcf/pcfdrivr.c index 6b4f30ac7..c0f0e49ca 100644 --- a/src/pcf/pcfdrivr.c +++ b/src/pcf/pcfdrivr.c @@ -442,7 +442,7 @@ THE SOFTWARE. FT_TRACE4(( "load_glyph %d ---", glyph_index )); - if ( !face ) + if ( !face || glyph_index >= (FT_UInt)face->root.num_glyphs ) { error = PCF_Err_Invalid_Argument; goto Exit; diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c index 8d29d5f30..f891cf595 100644 --- a/src/pfr/pfrobjs.c +++ b/src/pfr/pfrobjs.c @@ -296,8 +296,11 @@ if ( gindex > 0 ) gindex--; - /* check that the glyph index is correct */ - FT_ASSERT( gindex < face->phy_font.num_chars ); + if ( !face || gindex >= face->phy_font.num_chars ) + { + error = PFR_Err_Invalid_Argument; + goto Exit; + } /* try to load an embedded bitmap */ if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 ) diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c index 24cbd0eaf..828b264e5 100644 --- a/src/truetype/ttdriver.c +++ b/src/truetype/ttdriver.c @@ -243,6 +243,7 @@ { TT_GlyphSlot slot = (TT_GlyphSlot)ttslot; TT_Size size = (TT_Size)ttsize; + FT_Face face = ttslot->face; FT_Error error; @@ -252,6 +253,9 @@ if ( !size ) return TT_Err_Invalid_Size_Handle; + if ( !face || glyph_index >= (FT_UInt)face->num_glyphs ) + return TT_Err_Invalid_Argument; + if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) ) { load_flags |= FT_LOAD_NO_HINTING | diff --git a/src/type1/t1gload.c b/src/type1/t1gload.c index 7012b4ac2..e08a42897 100644 --- a/src/type1/t1gload.c +++ b/src/type1/t1gload.c @@ -225,6 +225,12 @@ #endif + if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) + { + error = T1_Err_Invalid_Argument; + goto Exit; + } + FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); if ( load_flags & FT_LOAD_NO_RECURSE ) diff --git a/src/winfonts/winfnt.c b/src/winfonts/winfnt.c index 3523b14f8..d3d602426 100644 --- a/src/winfonts/winfnt.c +++ b/src/winfonts/winfnt.c @@ -649,7 +649,8 @@ FT_UNUSED( load_flags ); - if ( !face || !font ) + if ( !face || !font || + glyph_index >= (FT_UInt)( FT_FACE( face )->num_glyphs ) ) { error = FNT_Err_Invalid_Argument; goto Exit;