Commit b4e06818ed2f570c9da2bb094291e0b708527c57

Werner Lemberg 2012-02-11T20:56:10

[truetype] Fix Savannah bug #35466. Jump instructions are now bound to the current function. The MS Windows rasterizer behaves the same, as confirmed by Greg Hitchcock. * src/truetype/ttinterp.h (TT_CallRec): Add `Cur_End' element. * src/truetype/ttobjs.h (TT_DefRecord): Add `end' element. * src/truetype/ttinterp.c (DO_JROT, DO_JMPR, DO_JROF): Check upper bound of jump address. (Ins_FDEF, Ins_CALL, Ins_LOOPCALL, Ins_UNKNOWN, TT_RunIns): Updated.

diff --git a/ChangeLog b/ChangeLog
index 02efbf2..34515fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2012-02-11  Werner Lemberg  <wl@gnu.org>
 
+	[truetype] Fix Savannah bug #35466.
+
+	Jump instructions are now bound to the current function.  The MS
+	Windows rasterizer behaves the same, as confirmed by Greg Hitchcock.
+
+	* src/truetype/ttinterp.h (TT_CallRec): Add `Cur_End' element.
+	* src/truetype/ttobjs.h (TT_DefRecord): Add `end' element.
+
+	* src/truetype/ttinterp.c (DO_JROT, DO_JMPR, DO_JROF): Check upper
+	bound of jump address.
+	(Ins_FDEF, Ins_CALL, Ins_LOOPCALL, Ins_UNKNOWN, TT_RunIns): Updated.
+
+2012-02-11  Werner Lemberg  <wl@gnu.org>
+
 	We don't use `extensions'.
 
 	* include/freetype/internal/ftobjs.h (FT_DriverRec): Remove
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 6ac4be5..752732a 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -715,7 +715,7 @@
     FT_Error  error;
 
 
-    if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0  ) )
+    if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
            != TT_Err_Ok )
       return error;
 
@@ -1800,7 +1800,7 @@
 
     /* NOTE: Because the last instruction of a program may be a CALL */
     /*       which will return to the first byte *after* the code    */
-    /*       range, we test for AIP <= Size, instead of AIP < Size.  */
+    /*       range, we test for aIP <= Size, instead of aIP < Size.  */
 
     if ( aIP > range->size )
     {
@@ -2757,7 +2757,7 @@
     W = Vx * Vx + Vy * Vy;
 
     /* Now, we want that Sqrt( W ) = 0x4000 */
-    /* Or 0x10000000 <= W < 0x10004000        */
+    /* Or 0x10000000 <= W < 0x10004000      */
 
     if ( Vx < 0 )
     {
@@ -3199,36 +3199,42 @@
   }
 
 
-#define DO_JROT                            \
-    if ( args[1] != 0 )                    \
-    {                                      \
-      if ( args[0] == 0 && CUR.args == 0 ) \
-        CUR.error = TT_Err_Bad_Argument;   \
-      CUR.IP += args[0];                   \
-      if ( CUR.IP < 0 )                    \
-        CUR.error = TT_Err_Bad_Argument;   \
-      CUR.step_ins = FALSE;                \
+#define DO_JROT                                                   \
+    if ( args[1] != 0 )                                           \
+    {                                                             \
+      if ( args[0] == 0 && CUR.args == 0 )                        \
+        CUR.error = TT_Err_Bad_Argument;                          \
+      CUR.IP += args[0];                                          \
+      if ( CUR.IP < 0                                          || \
+           ( CUR.callTop > 0                                 &&   \
+             CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) )  \
+        CUR.error = TT_Err_Bad_Argument;                          \
+      CUR.step_ins = FALSE;                                       \
     }
 
 
-#define DO_JMPR                          \
-    if ( args[0] == 0 && CUR.args == 0 ) \
-      CUR.error = TT_Err_Bad_Argument;   \
-    CUR.IP += args[0];                   \
-    if ( CUR.IP < 0 )                    \
-      CUR.error = TT_Err_Bad_Argument;   \
+#define DO_JMPR                                                 \
+    if ( args[0] == 0 && CUR.args == 0 )                        \
+      CUR.error = TT_Err_Bad_Argument;                          \
+    CUR.IP += args[0];                                          \
+    if ( CUR.IP < 0                                          || \
+         ( CUR.callTop > 0                                 &&   \
+           CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) )  \
+      CUR.error = TT_Err_Bad_Argument;                          \
     CUR.step_ins = FALSE;
 
 
-#define DO_JROF                            \
-    if ( args[1] == 0 )                    \
-    {                                      \
-      if ( args[0] == 0 && CUR.args == 0 ) \
-        CUR.error = TT_Err_Bad_Argument;   \
-      CUR.IP += args[0];                   \
-      if ( CUR.IP < 0 )                    \
-        CUR.error = TT_Err_Bad_Argument;   \
-      CUR.step_ins = FALSE;                \
+#define DO_JROF                                                   \
+    if ( args[1] == 0 )                                           \
+    {                                                             \
+      if ( args[0] == 0 && CUR.args == 0 )                        \
+        CUR.error = TT_Err_Bad_Argument;                          \
+      CUR.IP += args[0];                                          \
+      if ( CUR.IP < 0                                          || \
+           ( CUR.callTop > 0                                 &&   \
+             CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) )  \
+        CUR.error = TT_Err_Bad_Argument;                          \
+      CUR.step_ins = FALSE;                                       \
     }
 
 
@@ -4640,6 +4646,7 @@
         return;
 
       case 0x2D:   /* ENDF */
+        rec->end = CUR.IP;
         return;
       }
     }
@@ -4757,6 +4764,7 @@
     pCrec->Caller_IP    = CUR.IP + 1;
     pCrec->Cur_Count    = 1;
     pCrec->Cur_Restart  = def->start;
+    pCrec->Cur_End      = def->end;
 
     CUR.callTop++;
 
@@ -4835,6 +4843,7 @@
       pCrec->Caller_IP    = CUR.IP + 1;
       pCrec->Cur_Count    = (FT_Int)args[0];
       pCrec->Cur_Restart  = def->start;
+      pCrec->Cur_End      = def->end;
 
       CUR.callTop++;
 
@@ -7173,6 +7182,7 @@
         call->Caller_IP    = CUR.IP + 1;
         call->Cur_Count    = 1;
         call->Cur_Restart  = def->start;
+        call->Cur_End      = def->end;
 
         INS_Goto_CodeRange( def->range, def->start );
 
@@ -8181,6 +8191,7 @@
                 callrec->Caller_IP    = CUR.IP + 1;
                 callrec->Cur_Count    = 1;
                 callrec->Cur_Restart  = def->start;
+                callrec->Cur_End      = def->end;
 
                 if ( INS_Goto_CodeRange( def->range, def->start ) == FAILURE )
                   goto LErrorLabel_;
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index c480dfa..6d0fc03 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -102,6 +102,7 @@ FT_BEGIN_HEADER
     FT_Long  Caller_IP;
     FT_Long  Cur_Count;
     FT_Long  Cur_Restart;
+    FT_Long  Cur_End;
 
   } TT_CallRec, *TT_CallStack;
 
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index 087b3c2..47e4129 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Objects manager (specification).                                     */
 /*                                                                         */
-/*  Copyright 1996-2009, 2011 by                                           */
+/*  Copyright 1996-2009, 2011-2012 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -175,6 +175,7 @@ FT_BEGIN_HEADER
   {
     FT_Int   range;      /* in which code range is it located? */
     FT_Long  start;      /* where does it start?               */
+    FT_Long  end;        /* where does it end?                 */
     FT_UInt  opc;        /* function #, or instruction code    */
     FT_Bool  active;     /* is it active?                      */