Commit 4795b36cf9a4fa37d9c2aa0a2ac4d8ee9d2bc2b3

Werner Lemberg 2003-10-23T16:24:10

* src/type1/t1load.c (parse_encoding): Handle `/Encoding [ ... ]'. * src/type1/t1parse.c (T1_Get_Private_Dict): Test whether `eexec' is real. * src/type42/t42parse.c (t42_parse_encoding): Improve boundary checking while parsing. * docs/CHANGES: Updated.

diff --git a/ChangeLog b/ChangeLog
index 5b2aa8f..1d82f64 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2003-10-22  Werner Lemberg  <wl@gnu.org>
+
+	* src/type1/t1load.c (parse_encoding): Handle `/Encoding [ ... ]'.
+
+	* src/type1/t1parse.c (T1_Get_Private_Dict): Test whether `eexec'
+	is real.
+
+	* src/type42/t42parse.c (t42_parse_encoding): Improve boundary
+	checking while parsing.
+
+	* docs/CHANGES: Updated.
+
 2003-10-21  Josselin Mouette  <joss@debian.org>
 
 	* include/freetype/internal/t1types.h (T1_FontRec): `paint_type'
@@ -488,7 +500,7 @@
 	step towards a massive simplification of the engine's internals, in
 	order to get rid of various numbers of hacks.
 
-	Note that this changes will break source & binary compatibility for
+	Note that these changes will break source & binary compatibility for
 	authors of external font drivers.
 
 	* include/freetype/config/ftconfig.h (FT_BEGIN_STMNT, FT_END_STMNT,
diff --git a/docs/CHANGES b/docs/CHANGES
index c95658c..b404d92 100644
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -9,6 +9,15 @@ LATEST CHANGES BETWEEN 2.1.6 and 2.1.5
     - Type 1 font  files in  binary format  (PFB) with  an end-of-file
       indicator weren't accepted by the FreeType engine.
 
+    - Fonts which contain /PaintType  and /StrokeWidth no longer cause
+      a segfault.  This bug has been introduced in version 2.1.5.
+
+    - Fonts  loaded  with   FT_LOAD_RENDER  no  longer  cause  strange
+      results.  This bug has been introduced in version 2.1.5.
+
+    - Some  Windows   (bitmap)  FNT/FON  files   couldn't  be  handled
+      correctly.
+
   II. IMPORTANT CHANGES
 
     - The internal  module API  has been heavily  changed in  favor of
@@ -16,6 +25,10 @@ LATEST CHANGES BETWEEN 2.1.6 and 2.1.5
       that authors of third-party modules must adapt their code to the
       new scheme.
 
+    - The PostScript  parser has been enhanced to  handle comments and
+      strings   correctly.   Additionally,   more  syntax   forms  are
+      recognized.
+
 
 =====================================================================
 
@@ -39,14 +52,14 @@ LATEST CHANGES BETWEEN 2.1.5 and 2.1.4
       longer overwritten.
 
     - The font matrix  wasn't applied to the advance  width for Type1,
-      CID, and  CFF fonts.  This  caused problem when  loading certain
-      synthetic Type 1 fonts like "Helvetica Narrow"
+      CID, and  CFF fonts.  This caused problems  when loading certain
+      synthetic Type 1 fonts like `Helvetica Narrow'.
 
     - The test  for the charset registry  in BDF and PCF  fonts is now
       case-insensitive.
 
-    - FT_Vector_Rotate rotating sometimes  returned strange values due
-      to rounding errors.
+    - FT_Vector_Rotate  sometimes  returned   strange  values  due  to
+      rounding errors.
 
     - The  PCF  driver  now  returns  the  correct  number  of  glyphs
       (including an artificial `notdef' glyph at index 0).
diff --git a/src/type1/t1load.c b/src/type1/t1load.c
index 0aee92e..886e6cf 100644
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -884,19 +884,28 @@
       return;
     }
 
-    /* if we have a number, then the encoding is an array, */
-    /* and we must load it now                             */
-    if ( ft_isdigit( *cur ) )
+    /* if we have a number or `[', the encoding is an array, */
+    /* and we must load it now                               */
+    if ( ft_isdigit( *cur ) || *cur == '[' )
     {
-      T1_Encoding  encode     = &face->type1.encoding;
+      T1_Encoding  encode          = &face->type1.encoding;
       FT_Int       count, n;
-      PS_Table     char_table = &loader->encoding_table;
-      FT_Memory    memory     = parser->root.memory;
+      PS_Table     char_table      = &loader->encoding_table;
+      FT_Memory    memory          = parser->root.memory;
       FT_Error     error;
+      FT_Bool      only_immediates = 0;
 
 
       /* read the number of entries in the encoding; should be 256 */
-      count = (FT_Int)T1_ToInt( parser );
+      if ( *cur == '[' )
+      {
+        count           = 256;
+        only_immediates = 1;
+        parser->root.cursor++;
+      }
+      else
+        count = (FT_Int)T1_ToInt( parser );
+
       T1_Skip_Spaces( parser );
       if ( parser->root.cursor >= limit )
         return;
@@ -921,16 +930,25 @@
         T1_Add_Table( char_table, n, notdef, 8 );
       }
 
-      /* Now we need to read a record of the form               */
-      /* ... charcode /charname ... for each entry in our table */
+      /* Now we need to read records of the form                */
+      /*                                                        */
+      /*   ... charcode /charname ...                           */
+      /*                                                        */
+      /* for each entry in our table.                           */
       /*                                                        */
       /* We simply look for a number followed by an immediate   */
       /* name.  Note that this ignores correctly the sequence   */
-      /* that is often seen in Type 1 fonts:                    */
+      /* that is often seen in type1 fonts:                     */
       /*                                                        */
       /*   0 1 255 { 1 index exch /.notdef put } for dup        */
       /*                                                        */
       /* used to clean the encoding array before anything else. */
+      /*                                                        */
+      /* Alternatively, if the array is directly given as       */
+      /*                                                        */
+      /*   /Encoding [ ... ]                                    */
+      /*                                                        */
+      /* we only read immediates.                               */
 
       n = 0;
       T1_Skip_Spaces( parser );
@@ -939,7 +957,7 @@
       {
         cur = parser->root.cursor;
 
-        /* we stop when we encounter a `def' */
+        /* we stop when we encounter a `def' or `]' */
         if ( *cur == 'd' && cur + 3 < limit )
         {
           if ( cur[1] == 'e'      &&
@@ -951,18 +969,30 @@
             break;
           }
         }
+        if ( *cur == ']' )
+        {
+          FT_TRACE6(( "encoding end\n" ));
+          cur++;
+          break;
+        }
 
-        /* otherwise, we must find a number before anything else */
-        if ( ft_isdigit( *cur ) )
+        /* check whether we've found an entry */
+        if ( ft_isdigit( *cur ) || only_immediates )
         {
           FT_Int  charcode;
 
 
-          charcode = (FT_Int)T1_ToInt( parser );
-          T1_Skip_Spaces( parser );
+          if ( only_immediates )
+            charcode = n;
+          else
+          {
+            charcode = (FT_Int)T1_ToInt( parser );
+            T1_Skip_Spaces( parser );
+          }
+
           cur = parser->root.cursor;
 
-          if ( *cur == '/' && cur + 2 < limit )
+          if ( *cur == '/' && cur + 2 < limit && n < count )
           {
             FT_PtrDist  len;
 
@@ -979,6 +1009,8 @@
             char_table->elements[charcode][len] = '\0';
             if ( parser->root.error )
               return;
+
+            n++;
           }
         }
         else
diff --git a/src/type1/t1parse.c b/src/type1/t1parse.c
index 5a38063..cc0c2f3 100644
--- a/src/type1/t1parse.c
+++ b/src/type1/t1parse.c
@@ -299,24 +299,18 @@
       FT_Byte   c;
 
 
+    Again:
       for (;;)
       {
         c = cur[0];
         if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
                                             /* newline + 4 chars           */
         {
-          if ( cur[1] == 'e' && cur[2] == 'x' &&
-               cur[3] == 'e' && cur[4] == 'c' )
-          {
-            cur += 6; /* we skip the newline after the `eexec' */
-
-            /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
-            /*      skip the extra \n if we find it                     */
-            if ( cur[0] == '\n' )
-              cur++;
-
+          if ( cur[1] == 'e' &&
+               cur[2] == 'x' &&
+               cur[3] == 'e' &&
+               cur[4] == 'c' )
             break;
-          }
         }
         cur++;
         if ( cur >= limit )
@@ -328,10 +322,43 @@
         }
       }
 
+      /* check whether `eexec' was real -- it could be in a comment */
+      /* or string (as e.g. in u003043t.gsf from ghostscript)       */
+
+      parser->root.cursor = parser->base_dict;
+      parser->root.limit  = cur + 9;
+
+      cur   = parser->root.cursor;
+      limit = parser->root.limit;
+
+      while ( cur < limit )
+      {
+        if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
+          goto Found;
+
+        T1_Skip_PS_Token( parser );
+        T1_Skip_Spaces  ( parser );
+        cur = parser->root.cursor;
+      }
+
+      /* we haven't found the correct `eexec'; go back and continue */
+      /* searching                                                  */
+
+      cur   = limit;
+      limit = parser->base_dict + parser->base_len;
+      goto Again;
+
       /* now determine where to write the _encrypted_ binary private  */
       /* dictionary.  We overwrite the base dictionary for disk-based */
       /* resources and allocate a new block otherwise                 */
 
+    Found:
+      parser->root.limit = parser->base_dict + parser->base_len;
+
+      T1_Skip_PS_Token( parser );
+      T1_Skip_Spaces  ( parser );
+      cur = parser->root.cursor;
+
       size = (FT_Long)( parser->base_len - ( cur - parser->base_dict ) );
 
       if ( parser->in_memory )
diff --git a/src/type42/t42parse.c b/src/type42/t42parse.c
index d22c6df..20dcb90 100644
--- a/src/type42/t42parse.c
+++ b/src/type42/t42parse.c
@@ -288,7 +288,6 @@
 
     T1_Skip_Spaces( parser );
     cur = parser->root.cursor;
-
     if ( cur >= limit )
     {
       FT_ERROR(( "t42_parse_encoding: out of bounds!\n" ));
@@ -363,10 +362,10 @@
       /* we only read immediates.                               */
 
       n = 0;
+      T1_Skip_Spaces( parser );
 
       while ( parser->root.cursor < limit )
       {
-        T1_Skip_Spaces( parser );
         cur = parser->root.cursor;
 
         /* we stop when we encounter `def' or `]' */
@@ -427,6 +426,8 @@
         }
         else
           T1_Skip_PS_Token( parser );
+
+        T1_Skip_Spaces( parser );
       }
 
       face->type1.encoding_type  = T1_ENCODING_TYPE_ARRAY;