[truetype] Avoid reexecution of `fpgm' and `prep' in case of error.

Reported as

  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=981

* include/freetype/fterrdef.h (FT_Err_DEF_In_Glyf_Bytecode): New
error code.

* src/truetype/ttinterp.c (Ins_FDEF, Ins_IDEF): Prohibit execution
of these two opcodes in `glyf' bytecode.
(TT_RunIns): Don't enforce reexecution of `fpgm' and `prep' bytecode
in case of error since function tables can no longer be modified
(due to the changes in `Ins_FDEF' and `Ins_IDEF').  This change can
enormously speed up handling of broken fonts.
diff --git a/ChangeLog b/ChangeLog
index f391958..b6cc3b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2017-04-03  Werner Lemberg  <wl@gnu.org>
+
+	[truetype] Avoid reexecution of `fpgm' and `prep' in case of error.
+
+	Reported as
+
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=981
+
+	* include/freetype/fterrdef.h (FT_Err_DEF_In_Glyf_Bytecode): New
+	error code.
+
+	* src/truetype/ttinterp.c (Ins_FDEF, Ins_IDEF): Prohibit execution
+	of these two opcodes in `glyf' bytecode.
+	(TT_RunIns): Don't enforce reexecution of `fpgm' and `prep' bytecode
+	in case of error since function tables can no longer be modified
+	(due to the changes in `Ins_FDEF' and `Ins_IDEF').  This change can
+	enormously speed up handling of broken fonts.
+
 2017-04-02  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
 	[autofit] Disable metrics adjustment for `FT_LOAD_TARGET_LCD'.
diff --git a/include/freetype/fterrdef.h b/include/freetype/fterrdef.h
index 232dccd..cabbac8 100644
--- a/include/freetype/fterrdef.h
+++ b/include/freetype/fterrdef.h
@@ -231,6 +231,8 @@
                 "invalid PostScript (post) table format" )
   FT_ERRORDEF_( Invalid_Post_Table,                          0x9B,
                 "invalid PostScript (post) table" )
+  FT_ERRORDEF_( DEF_In_Glyf_Bytecode,                        0x9C,
+                "found FDEF or IDEF opcode in glyf bytecode" )
 
   /* CFF, CID, and Type 1 errors */
 
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 000c30b..fed377d 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -3564,6 +3564,13 @@
 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
 
+    /* FDEF is only allowed in `prep' or `fpgm' */
+    if ( exc->curRange == tt_coderange_glyph )
+    {
+      exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
+      return;
+    }
+
     /* some font programs are broken enough to redefine functions! */
     /* We will then parse the current table.                       */
 
@@ -3990,6 +3997,13 @@
     TT_DefRecord*  limit;
 
 
+    /* we enable IDEF only in `prep' or `fpgm' */
+    if ( exc->curRange == tt_coderange_glyph )
+    {
+      exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
+      return;
+    }
+
     /*  First of all, look for the same function in our table */
 
     def   = exc->IDefs;
@@ -8408,17 +8422,8 @@
     exc->error = FT_THROW( Code_Overflow );
 
   LErrorLabel_:
-    /* If any errors have occurred, function tables may be broken. */
-    /* Force a re-execution of `prep' and `fpgm' tables if no      */
-    /* bytecode debugger is run.                                   */
-    if ( exc->error                          &&
-         !exc->instruction_trap              &&
-         exc->curRange == tt_coderange_glyph )
-    {
+    if ( exc->error && !exc->instruction_trap )
       FT_TRACE1(( "  The interpreter returned error 0x%x\n", exc->error ));
-      exc->size->bytecode_ready = -1;
-      exc->size->cvt_ready      = -1;
-    }
 
     return exc->error;
   }