ref: 2862686996955651538bf9e4481b52d3ff8bad74
parent: bc25de66c112a9ff4722264330ada77b6e651408
author: Werner Lemberg <[email protected]>
date: Wed Nov 20 16:06:18 EST 2013
[truetype] Don't trust `maxp's `maxSizeOfInstructions'. Problem reported by Hin-Tak Leung <[email protected]>; 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'.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2013-11-20 Werner Lemberg <[email protected]>
+
+ [truetype] Don't trust `maxp's `maxSizeOfInstructions'.
+
+ Problem reported by Hin-Tak Leung <[email protected]>; 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 <[email protected]>
[sfnt] Fix `OS/2' table version 5 support.
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -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;
}
}
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -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 );
}