* src/truetype/ttpload.c (tt_face_load_loca): Handle buggy fonts

where num_locations < num_glyphs.  Problem reported by Ding Li.
This commit is contained in:
Werner Lemberg 2008-07-09 06:20:12 +00:00
parent ca6fc732b7
commit 6b19e095be
2 changed files with 51 additions and 3 deletions

View File

@ -1,3 +1,8 @@
2008-07-09 Werner Lemberg <wl@gnu.org>
* src/truetype/ttpload.c (tt_face_load_loca): Handle buggy fonts
where num_locations < num_glyphs. Problem reported by Ding Li.
2008-07-05 Werner Lemberg <wl@gnu.org>
Since FreeType uses `$(value ...)', we now need GNU make 3.80 or

View File

@ -4,7 +4,7 @@
/* */
/* TrueType-specific tables loader (body). */
/* */
/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007 by */
/* Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@ -65,6 +65,7 @@
{
FT_Error error;
FT_ULong table_len;
FT_Int shift;
/* we need the size of the `glyf' table for malformed `loca' tables */
@ -82,23 +83,65 @@
if ( face->header.Index_To_Loc_Format != 0 )
{
shift = 2;
if ( table_len >= 0x40000L )
{
FT_TRACE2(( "table too large!\n" ));
error = TT_Err_Invalid_Table;
goto Exit;
}
face->num_locations = (FT_UInt)( table_len >> 2 );
face->num_locations = (FT_UInt)( table_len >> shift );
}
else
{
shift = 1;
if ( table_len >= 0x20000L )
{
FT_TRACE2(( "table too large!\n" ));
error = TT_Err_Invalid_Table;
goto Exit;
}
face->num_locations = (FT_UInt)( table_len >> 1 );
face->num_locations = (FT_UInt)( table_len >> shift );
}
if ( face->num_locations != (FT_UInt)face->root.num_glyphs )
{
FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
face->num_locations, face->root.num_glyphs ));
/* we only handle the case where `maxp' gives a larger value */
if ( face->num_locations < (FT_UInt)face->root.num_glyphs )
{
FT_Long new_loca_len = (FT_Long)face->root.num_glyphs << shift;
TT_Table entry = face->dir_tables;
TT_Table limit = entry + face->num_tables;
FT_Long pos = FT_Stream_Pos( stream );
FT_Long dist = 0x7FFFFFFFL;
/* compute the distance to next table in font file */
for ( ; entry < limit; entry++ )
{
FT_Long diff = entry->Offset - pos;
if ( diff > 0 && diff < dist )
dist = diff;
}
if ( new_loca_len <= dist )
{
face->num_locations = (FT_Long)face->root.num_glyphs;
table_len = new_loca_len;
FT_TRACE2(( "adjusting num_locations to %d\n",
face->num_locations ));
}
}
}
/*