diff --git a/ChangeLog b/ChangeLog index 4cf4d5a5b..a0ec37bbc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2017-03-18 Werner Lemberg + + [truetype] Another limitation for bytecode loop count maximum. + + Reported as + + https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=900 + + * src/truetype/ttinterp.c (TT_RunIns): Limit `loopcall_counter_max' + by number of glyphs also. + 2017-03-18 Werner Lemberg [ftfuzzer] Minor improvement. diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c index 44df298d5..f4f89b0e7 100644 --- a/src/truetype/ttinterp.c +++ b/src/truetype/ttinterp.c @@ -7605,15 +7605,16 @@ exc->twilight.n_points = (FT_UShort)num_twilight_points; } - /* Set up loop detectors. We restrict the number of LOOPCALL loops */ - /* and the number of JMPR, JROT, and JROF calls with a negative */ - /* argument to values that depend on the size of the CVT table and */ - /* the number of points in the current glyph (if applicable). */ - /* */ - /* The idea is that in real-world bytecode you either iterate over */ - /* all CVT entries (in the `prep' table), or over all points (or */ - /* contours, in the `glyf' table) of a glyph, and such iterations */ - /* don't happen very often. */ + /* Set up loop detectors. We restrict the number of LOOPCALL loops */ + /* and the number of JMPR, JROT, and JROF calls with a negative */ + /* argument to values that depend on various parameters like the */ + /* size of the CVT table or the number of points in the current */ + /* glyph (if applicable). */ + /* */ + /* The idea is that in real-world bytecode you either iterate over */ + /* all CVT entries (in the `prep' table), or over all points (or */ + /* contours, in the `glyf' table) of a glyph, and such iterations */ + /* don't happen very often. */ exc->loopcall_counter = 0; exc->neg_jump_counter = 0; @@ -7626,6 +7627,13 @@ else exc->loopcall_counter_max = FT_MAX( 100, 5 * exc->cvtSize ); + + /* as a protection against an unreasonable number of CVT entries */ + /* we assume at most 100 control values per glyph for the counter */ + if ( exc->loopcall_counter_max > + 100 * (FT_ULong)exc->face->root.num_glyphs ) + exc->loopcall_counter_max = 100 * (FT_ULong)exc->face->root.num_glyphs; + FT_TRACE5(( "TT_RunIns: Limiting total number of loops in LOOPCALL" " to %d\n", exc->loopcall_counter_max ));