shithub: freetype+ttf2subf

Download patch

ref: b553fcb514a5e7131d34a117bf2d01e034ab7a08
parent: b653a2307921c0319043c5f5ecc1243ee9786d87
author: Werner Lemberg <[email protected]>
date: Tue Feb 28 10:11:21 EST 2017

[sfnt] Further generalize `sfnt_get_ps_name'; report invalid data.

* src/sfnt/sfdriver.c (sfnt_ps_map): New array.
(sfnt_is_postscript): New function.
(char_type_func): New typedef.
(get_win_string, get_apple_string): Add argument to specify
character checking function.
Add argument whether argument checking failures should be reported.
Update callers.
(search_name_id): Fix return value.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2017-02-23  Werner Lemberg  <[email protected]>
 
+	[sfnt] Further generalize `sfnt_get_ps_name'; report invalid data.
+
+	* src/sfnt/sfdriver.c (sfnt_ps_map): New array.
+	(sfnt_is_postscript): New function.
+	(char_type_func): New typedef.
+	(get_win_string, get_apple_string): Add argument to specify
+	character checking function.
+	Add argument whether argument checking failures should be reported.
+	Update callers.
+	(search_name_id): Fix return value.
+
+2017-02-23  Werner Lemberg  <[email protected]>
+
 	[sfnt] Split off another bit of `sfnt_get_ps_name'.
 
 	* src/sfnt/sfdriver.c (sfnt_get_ps_name): Split off some
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -220,6 +220,39 @@
    *
    */
 
+  /* an array representing allowed ASCII characters in a PS string */
+  static const unsigned char sfnt_ps_map[16] =
+  {
+                /*             4        0        C        8 */
+    0x00, 0x00, /* 0x00: 0 0 0 0  0 0 0 0  0 0 0 0  0 0 0 0 */
+    0x00, 0x00, /* 0x10: 0 0 0 0  0 0 0 0  0 0 0 0  0 0 0 0 */
+    0xDE, 0x7C, /* 0x20: 1 1 0 1  1 1 1 0  0 1 1 1  1 1 0 0 */
+    0xFF, 0xAF, /* 0x30: 1 1 1 1  1 1 1 1  1 0 1 0  1 1 1 1 */
+    0xFF, 0xFF, /* 0x40: 1 1 1 1  1 1 1 1  1 1 1 1  1 1 1 1 */
+    0xFF, 0xD7, /* 0x50: 1 1 1 1  1 1 1 1  1 1 0 1  0 1 1 1 */
+    0xFF, 0xFF, /* 0x60: 1 1 1 1  1 1 1 1  1 1 1 1  1 1 1 1 */
+    0xFF, 0x57  /* 0x70: 1 1 1 1  1 1 1 1  0 1 0 1  0 1 1 1 */
+  };
+
+
+  static int
+  sfnt_is_postscript( int  c )
+  {
+    unsigned int  cc;
+
+
+    if ( c < 0 || c >= 0x80 )
+      return 0;
+
+    cc = (unsigned int)c;
+
+    return sfnt_ps_map[cc >> 3] & ( 1 << ( cc & 0x07 ) );
+  }
+
+
+  typedef int (*char_type_func)( int  c );
+
+
   /* handling of PID/EID 3/0 and 3/1 is the same */
 #define IS_WIN( n )  ( (n)->platformID == 3                             && \
                        ( (n)->encodingID == 1 || (n)->encodingID == 0 ) && \
@@ -230,9 +263,11 @@
                          (n)->languageID == 0 )
 
   static const char*
-  get_win_string( FT_Memory  memory,
-                  FT_Stream  stream,
-                  TT_Name    entry )
+  get_win_string( FT_Memory       memory,
+                  FT_Stream       stream,
+                  TT_Name         entry,
+                  char_type_func  char_type,
+                  FT_Bool         report_invalid_characters )
   {
     FT_Error  error = FT_Err_Ok;
 
@@ -263,8 +298,22 @@
 
     for ( len = entry->stringLength / 2; len > 0; len--, p += 2 )
     {
-      if ( p[0] == 0 && p[1] >= 32 )
-        *r++ = p[1];
+      if ( p[0] == 0 )
+      {
+        if ( char_type( p[1] ) )
+          *r++ = p[1];
+        else
+        {
+          if ( report_invalid_characters )
+          {
+            FT_TRACE0(( "get_win_string:"
+                        " Character `%c' (0x%X) invalid in PS name string\n",
+                        p[1], p[1] ));
+            /* it's not the job of FreeType to correct PS names... */
+            *r++ = p[1];
+          }
+        }
+      }
     }
     *r = '\0';
 
@@ -275,13 +324,18 @@
 
 
   static const char*
-  get_apple_string( FT_Memory  memory,
-                    FT_Stream  stream,
-                    TT_Name    entry )
+  get_apple_string( FT_Memory       memory,
+                    FT_Stream       stream,
+                    TT_Name         entry,
+                    char_type_func  char_type,
+                    FT_Bool         report_invalid_characters )
   {
     FT_Error  error = FT_Err_Ok;
 
     const char*  result;
+    FT_String*   r;
+    FT_Char*     p;
+    FT_UInt      len;
 
     FT_UNUSED( error );
 
@@ -289,8 +343,8 @@
     if ( FT_ALLOC( result, entry->stringLength + 1 ) )
       return NULL;
 
-    if ( FT_STREAM_SEEK( entry->stringOffset )         ||
-         FT_STREAM_READ( result, entry->stringLength ) )
+    if ( FT_STREAM_SEEK( entry->stringOffset ) ||
+         FT_FRAME_ENTER( entry->stringLength ) )
     {
       FT_FREE( result );
       entry->stringOffset = 0;
@@ -300,8 +354,29 @@
       return NULL;
     }
 
-    ((char*)result)[entry->stringLength] = '\0';
+    r = (FT_String*)result;
+    p = (FT_Char*)stream->cursor;
 
+    for ( len = entry->stringLength; len > 0; len--, p++ )
+    {
+      if ( char_type( *p ) )
+        *r++ = *p;
+      else
+      {
+        if ( report_invalid_characters )
+        {
+          FT_TRACE0(( "get_apple_string:"
+                      " Character `%c' (0x%X) invalid in PS name string\n",
+                      *p, *p ));
+          /* it's not the job of FreeType to correct PS names... */
+          *r++ = *p;
+        }
+      }
+    }
+    *r = '\0';
+
+    FT_FRAME_EXIT();
+
     return result;
   }
 
@@ -333,7 +408,7 @@
       }
     }
 
-    return *win || *apple;
+    return ( *win >= 0 ) || ( *apple >= 0 );
   }
 
 
@@ -340,7 +415,7 @@
   static const char*
   sfnt_get_ps_name( TT_Face  face )
   {
-    FT_Int       found_win, found_apple;
+    FT_Int       found, win, apple;
     const char*  result = NULL;
 
 
@@ -349,17 +424,24 @@
 
     /* scan the name table to see whether we have a Postscript name here, */
     /* either in Macintosh or Windows platform encodings                  */
-    search_name_id( face, 6, &found_win, &found_apple );
+    found = search_name_id( face, 6, &win, &apple );
 
-    /* prefer Windows entries over Apple */
-    if ( found_win != -1 )
-      result = get_win_string( face->root.memory,
-                               face->name_table.stream,
-                               face->name_table.names + found_win );
-    else if ( found_apple != -1 )
-      result = get_apple_string( face->root.memory,
+    if ( found )
+    {
+      /* prefer Windows entries over Apple */
+      if ( win != -1 )
+        result = get_win_string( face->root.memory,
                                  face->name_table.stream,
-                                 face->name_table.names + found_apple );
+                                 face->name_table.names + win,
+                                 sfnt_is_postscript,
+                                 1 );
+      else
+        result = get_apple_string( face->root.memory,
+                                   face->name_table.stream,
+                                   face->name_table.names + apple,
+                                   sfnt_is_postscript,
+                                   1 );
+    }
 
     face->postscript_name = result;