[truetype] Don't trust maxp's maxSizeOfInstructions'.

Problem reported by Hin-Tak Leung <htl10@users.sourceforge.net>; see

  http://lists.nongnu.org/archive/html/freetype-devel/2013-08/msg00005.html

for details.

* src/base/ftobjs.c (FT_Load_Glyph): Check size of `fpgm' and `prep'
tables also for setting `autohint'.

* src/truetype/ttgload.c (TT_Load_Simple_Glyph): Use code from
`TT_Process_Composite_Glyph' for handling unreliable values of
`maxSizeOfInstructions'.
This commit is contained in:
Werner Lemberg 2013-11-20 21:06:18 +01:00
parent bc25de66c1
commit 2862686996
3 changed files with 55 additions and 12 deletions

View File

@ -1,3 +1,20 @@
2013-11-20 Werner Lemberg <wl@gnu.org>
[truetype] Don't trust `maxp's `maxSizeOfInstructions'.
Problem reported by Hin-Tak Leung <htl10@users.sourceforge.net>; see
http://lists.nongnu.org/archive/html/freetype-devel/2013-08/msg00005.html
for details.
* src/base/ftobjs.c (FT_Load_Glyph): Check size of `fpgm' and `prep'
tables also for setting `autohint'.
* src/truetype/ttgload.c (TT_Load_Simple_Glyph): Use code from
`TT_Process_Composite_Glyph' for handling unreliable values of
`maxSizeOfInstructions'.
2013-11-16 Werner Lemberg <wl@gnu.org>
[sfnt] Fix `OS/2' table version 5 support.

View File

@ -665,11 +665,18 @@
/* the check for `num_locations' assures that we actually */
/* test for instructions in a TTF and not in a CFF-based OTF */
/* */
/* since `maxSizeOfInstructions' might be unreliable, we */
/* check the size of the `fpgm' and `prep' tables, too -- */
/* the assumption is that there don't exist real TTFs where */
/* both `fpgm' and `prep' tables are missing */
if ( mode == FT_RENDER_MODE_LIGHT ||
face->internal->ignore_unpatented_hinter ||
( FT_IS_SFNT( face ) &&
ttface->num_locations &&
ttface->max_profile.maxSizeOfInstructions == 0 ) )
ttface->max_profile.maxSizeOfInstructions == 0 &&
ttface->font_program_size == 0 &&
ttface->cvt_program_size == 0 ) )
autohint = TRUE;
}
}

View File

@ -349,8 +349,9 @@
FT_Int n_contours = load->n_contours;
FT_Outline* outline;
TT_Face face = (TT_Face)load->face;
FT_UShort n_ins;
FT_UShort n_ins, max_ins;
FT_Int n_points;
FT_ULong tmp;
FT_Byte *flag, *flag_limit;
FT_Byte c, count;
@ -416,12 +417,29 @@
FT_TRACE5(( " Instructions size: %u\n", n_ins ));
if ( n_ins > face->max_profile.maxSizeOfInstructions )
/* check it */
max_ins = face->max_profile.maxSizeOfInstructions;
if ( n_ins > max_ins )
{
FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",
n_ins ));
error = FT_THROW( Too_Many_Hints );
goto Fail;
/* don't trust `maxSizeOfInstructions'; */
/* only do a rough safety check */
if ( (FT_Int)n_ins > load->byte_len )
{
FT_TRACE1(( "TT_Load_Simple_Glyph:"
" too many instructions (%d) for glyph with length %d\n",
n_ins, load->byte_len ));
return FT_THROW( Too_Many_Hints );
}
tmp = load->exec->glyphSize;
error = Update_Max( load->exec->memory,
&tmp,
sizeof ( FT_Byte ),
(void*)&load->exec->glyphIns,
n_ins );
load->exec->glyphSize = (FT_UShort)tmp;
if ( error )
return error;
}
if ( ( limit - p ) < n_ins )
@ -743,8 +761,8 @@
#ifdef TT_USE_BYTECODE_INTERPRETER
if ( loader->glyph->control_len > 0xFFFFL )
{
FT_TRACE1(( "TT_Hint_Glyph: too long instructions " ));
FT_TRACE1(( "(0x%lx byte) is truncated\n",
FT_TRACE1(( "TT_Hint_Glyph: too long instructions" ));
FT_TRACE1(( " (0x%lx byte) is truncated\n",
loader->glyph->control_len ));
}
n_ins = (FT_UInt)( loader->glyph->control_len );
@ -1216,11 +1234,12 @@
max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions;
if ( n_ins > max_ins )
{
/* acroread ignores this field, so we only do a rough safety check */
/* don't trust `maxSizeOfInstructions'; */
/* only do a rough safety check */
if ( (FT_Int)n_ins > loader->byte_len )
{
FT_TRACE1(( "TT_Process_Composite_Glyph: "
"too many instructions (%d) for glyph with length %d\n",
FT_TRACE1(( "TT_Process_Composite_Glyph:"
" too many instructions (%d) for glyph with length %d\n",
n_ins, loader->byte_len ));
return FT_THROW( Too_Many_Hints );
}