Commit 13fa85a246d5fddc037ef3f11e61f9cf0ff3b2be

Werner Lemberg 2017-03-18T09:42:58

[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.

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 ));