Commit e7389a4405223c40e552122451c7612ae030c20d

Werner Lemberg 2009-06-28T01:25:55

[psaux, cff] Protect against nested `seac' calls. * include/freetype/internal/psaux.h (T1_Decoder), src/cff/cffgload.h (CFF_Decoder): Add `seac' boolean variable. * src/cff/cffgload.c (cff_operator_seac, cff_decoder_parse_charstrings), src/psaux/t1decode.c (t1operator_seac, t1_decoder_parse_charstrings): Use it.

diff --git a/ChangeLog b/ChangeLog
index 6c62411..df11d1b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2009-06-28  Werner Lemberg  <wl@gnu.org>
 
+	[psaux, cff] Protect against nested `seac' calls.
+
+	* include/freetype/internal/psaux.h (T1_Decoder), src/cff/cffgload.h
+	(CFF_Decoder): Add `seac' boolean variable.
+
+	* src/cff/cffgload.c (cff_operator_seac,
+	cff_decoder_parse_charstrings), src/psaux/t1decode.c
+	(t1operator_seac, t1_decoder_parse_charstrings): Use it.
+
+2009-06-28  Werner Lemberg  <wl@gnu.org>
+
 	Thinko.
 
 	* src/psaux/t1decode.c (t1operator_seac)
diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h
index cac9f47..503eb2b 100644
--- a/include/freetype/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -692,6 +692,8 @@ FT_BEGIN_HEADER
     FT_Int*              buildchar;
     FT_UInt              len_buildchar;
 
+    FT_Bool              seac;
+
   } T1_DecoderRec;
 
 
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index d216312..2a982f4 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -707,6 +707,12 @@
     FT_ULong      charstring_len;
 
 
+    if ( decoder->seac )
+    {
+      FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
+      return CFF_Err_Syntax_Error;
+    }
+
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     /* Incremental fonts don't necessarily have valid charsets.        */
     /* They use the character code, not the glyph index, in this case. */
@@ -1883,11 +1889,14 @@
             FT_Pos  glyph_width = decoder->glyph_width;
 
 
+            /* the seac operator must not be nested */
+            decoder->seac = TRUE;
             error = cff_operator_seac( decoder,
                                        args[-4],
                                        args[-3],
                                        (FT_Int)( args[-2] >> 16 ),
                                        (FT_Int)( args[-1] >> 16 ) );
+            decoder->seac = FALSE;
 
             decoder->glyph_width = glyph_width;
           }
diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h
index ff28670..956817a 100644
--- a/src/cff/cffgload.h
+++ b/src/cff/cffgload.h
@@ -154,6 +154,8 @@ FT_BEGIN_HEADER
 
     FT_Render_Mode     hint_mode;
 
+    FT_Bool            seac;
+
   } CFF_Decoder;
 
 
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index fcd7d57..39b5c8b 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -198,6 +198,13 @@
     T1_Face      face  = (T1_Face)decoder->builder.face;
 #endif     
 
+
+    if ( decoder->seac )
+    {
+      FT_ERROR(( "t1operator_seac: invalid nested seac\n" ));
+      return PSaux_Err_Syntax_Error;
+    }
+
     /* seac weirdness */
     adx += decoder->builder.left_bearing.x;
 
@@ -1118,13 +1125,18 @@
           break;
 
         case op_seac:
+          /* the seac operator must not be nested */
+          decoder->seac = TRUE;
+          error = t1operator_seac( decoder,
+                                   top[0],
+                                   top[1],
+                                   top[2],
+                                   (FT_Int)( top[3] >> 16 ),
+                                   (FT_Int)( top[4] >> 16 ) );
+          decoder->seac = FALSE;
+
           /* return immediately after the processing */
-          return t1operator_seac( decoder,
-                                  top[0],
-                                  top[1],
-                                  top[2],
-                                  (FT_Int)( top[3] >> 16 ),
-                                  (FT_Int)( top[4] >> 16 ) );
+          return error;
 
         case op_sbw:
           FT_TRACE4(( " sbw" ));