[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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
diff --git a/ChangeLog b/ChangeLog
index 4cf4d5a..a0ec37b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2017-03-18 Werner Lemberg <wl@gnu.org>
+ [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 <wl@gnu.org>
+
[ftfuzzer] Minor improvement.
* src/tools/ftfuzzer/ftfuzzer.cc: Don't set intermediate axis if
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 44df298..f4f89b0 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 ));