shithub: freetype+ttf2subf

Download patch

ref: 0ae3271814982524dfd210dee09031c2430d473f
parent: 8a6f3280f5c88187c5fc5871d35a4750156db6e0
author: suzuki toshiya <[email protected]>
date: Sun Jul 4 16:14:18 EDT 2010

Restrict the number of the charmaps in a rogue-compatible mode.
Fix for Savannah bug #30059.

* src/cache/ftccmap.c (FTC_CMapCache_Lookup): Replace `16' the
minimum character code passed by a legacy rogue client by...
* include/freetype/config/ftoption.h (FT_MAX_CHARMAP_CACHEABLE):
This.  It is undefined when FT_CONFIG_OPTION_OLD_INTERNALS is
undefined (thus the rogue client compatibility is not required).

* src/cff/cffobjs.c (cff_face_init): Abort the automatic
selection or synthesis of Unicode cmap subtable when the charmap
index exceeds FT_MAX_CHARMAP_CACHEABLE.
* src/sfnt/ttcmap.c (tt_face_build_cmaps): Issue error message
when the charmap index exceeds FT_MAX_CHARMAP_CACHEABLE.

* src/base/ftobjs.c (find_unicode_charmap): When Unicode charmap
is found after FT_MAX_CHARMAP_CACHEABLE, ignore it and search
earlier one.
(find_variant_selector_charmap): When UVS charmap is found after
FT_MAX_CHARMAP_CACHEABLE, ignore it and search earlier one.
(FT_Select_Charmap): When a charmap matching with requested
encoding but after FT_MAX_CHARMAP_CACHEABLE, ignore and search
earlier one.
(FT_Set_Charmap): When a charmap matching with requested
charmap but after FT_MAX_CHARMAP_CACHEABLE, ignore and search
earlier one.
(FT_Get_Charmap_Index): When a requested charmap is found
after FT_MAX_CHARMAP_CACHEABLE, return the inverted charmap
index.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2010-07-04  suzuki toshiya  <[email protected]>
+
+	Restrict the number of the charmaps in a rogue-compatible mode.
+	Fix for Savannah bug #30059.
+
+	* src/cache/ftccmap.c (FTC_CMapCache_Lookup): Replace `16' the
+	minimum character code passed by a legacy rogue client by...
+	* include/freetype/config/ftoption.h (FT_MAX_CHARMAP_CACHEABLE):
+	This.  It is undefined when FT_CONFIG_OPTION_OLD_INTERNALS is
+	undefined (thus the rogue client compatibility is not required).
+
+	* src/cff/cffobjs.c (cff_face_init): Abort the automatic
+	selection or synthesis of Unicode cmap subtable when the charmap
+	index exceeds FT_MAX_CHARMAP_CACHEABLE.
+	* src/sfnt/ttcmap.c (tt_face_build_cmaps): Issue error message
+	when the charmap index exceeds FT_MAX_CHARMAP_CACHEABLE.
+
+	* src/base/ftobjs.c (find_unicode_charmap): When Unicode charmap
+	is found after FT_MAX_CHARMAP_CACHEABLE, ignore it and search
+	earlier one.
+	(find_variant_selector_charmap): When UVS charmap is found after
+	FT_MAX_CHARMAP_CACHEABLE, ignore it and search earlier one.
+	(FT_Select_Charmap): When a charmap matching with requested
+	encoding but after FT_MAX_CHARMAP_CACHEABLE, ignore and search
+	earlier one.
+	(FT_Set_Charmap): When a charmap matching with requested
+	charmap but after FT_MAX_CHARMAP_CACHEABLE, ignore and search
+	earlier one.
+	(FT_Get_Charmap_Index): When a requested charmap is found
+	after FT_MAX_CHARMAP_CACHEABLE, return the inverted charmap
+	index.
+
 2010-07-04  Werner Lemberg  <[email protected]>
 
 	TrueType hinting is no longer patented.
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -693,6 +693,27 @@
 
 
   /*
+   *  To detect legacy cache-lookup call from a rogue client (<= 2.1.7),
+   *  we restrict the number of charmaps in a font.  The current API of
+   *  FTC_CMapCache_Lookup() takes cmap_index & charcode, but old API
+   *  takes charcode only.  To determine the passed value is for cmap_index
+   *  or charcode, the possible cmap_index is restricted not to exceed
+   *  the minimum possible charcode by a rogue client.  It is also very
+   *  unlikely that a rogue client is interested in Unicode values 0 to 15.
+   *
+   *  NOTE: The original threshold was 4 deduced from popular number of
+   *        cmap subtables in UCS-4 TrueType fonts, but now it is not
+   *        irregular for OpenType fonts to have more than 4 subtables,
+   *        because variation selector subtables are available for Apple
+   *        and Microsoft platforms.
+   */
+
+#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+#define FT_MAX_CHARMAP_CACHEABLE 15
+#endif
+
+
+  /*
    * This macro is defined if either unpatented or native TrueType
    * hinting is requested by the definitions above.
    */
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -991,6 +991,14 @@
              ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE &&
                cur[0]->encoding_id == TT_APPLE_ID_UNICODE_32    ) )
         {
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+          if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
+          {
+            FT_ERROR(( "find_unicode_charmap: UCS-4 cmap is found "
+                       "at too late position (%d)\n", cur - first ));
+            continue;
+          }
+#endif
           face->charmap = cur[0];
           return FT_Err_Ok;
         }
@@ -1005,6 +1013,14 @@
     {
       if ( cur[0]->encoding == FT_ENCODING_UNICODE )
       {
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+        if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
+        {
+          FT_ERROR(( "find_unicode_charmap: UCS-2 cmap is found "
+                     "at too late position (%d)\n", cur - first ));
+          continue;
+        }
+#endif
         face->charmap = cur[0];
         return FT_Err_Ok;
       }
@@ -1046,6 +1062,14 @@
       if ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE    &&
            cur[0]->encoding_id == TT_APPLE_ID_VARIANT_SELECTOR &&
            FT_Get_CMap_Format( cur[0] ) == 14                  )
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+        if ( cur - first > FT_MAX_CHARMAP_CACHEABLE )
+        {
+          FT_ERROR(( "find_unicode_charmap: UVS cmap is found "
+                     "at too late position (%d)\n", cur - first ));
+          continue;
+        }
+#endif
         return cur[0];
     }
 
@@ -2922,6 +2946,15 @@
     {
       if ( cur[0]->encoding == encoding )
       {
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+        if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
+        {
+          FT_ERROR(( "FT_Select_Charmap: requested charmap is found (%d), "
+                     "but in too late position to cache\n",
+                     cur - face->charmaps ));
+          continue;
+        }
+#endif
         face->charmap = cur[0];
         return 0;
       }
@@ -2956,6 +2989,15 @@
     {
       if ( cur[0] == charmap )
       {
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+        if ( cur - face->charmaps > FT_MAX_CHARMAP_CACHEABLE )
+        {
+          FT_ERROR(( "FT_Set_Charmap: requested charmap is found (%d), "
+                     "but in too late position to cache\n",
+                     cur - face->charmaps ));
+          continue;
+        }
+#endif
         face->charmap = cur[0];
         return 0;
       }
@@ -2981,6 +3023,15 @@
 
     FT_ASSERT( i < charmap->face->num_charmaps );
 
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+    if ( i > FT_MAX_CHARMAP_CACHEABLE )
+    {
+      FT_ERROR(( "FT_Get_Charmap_Index: requested charmap is found (%d), "
+                 "but in too late position to cache\n",
+                 i ));
+      return -i;
+    }
+#endif
     return i;
   }
 
--- a/src/cache/ftccmap.c
+++ b/src/cache/ftccmap.c
@@ -310,19 +310,11 @@
 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
 
     /*
-     *  Detect a call from a rogue client that thinks it is linking
-     *  to FreeType 2.1.7.  This is possible because the third parameter
-     *  is then a character code, and we have never seen any font with
-     *  more than a few charmaps, so if the index is very large...
-     *
-     *  It is also very unlikely that a rogue client is interested
-     *  in Unicode values 0 to 15.
-     *
-     *  NOTE: The original threshold was 4, but we found a font from the
-     *        Adobe Acrobat Reader Pack, named `KozMinProVI-Regular.otf',
-     *        which contains more than 5 charmaps.
+     * If cmap_index is greater than the maximum number of cachable
+     * charmaps, we assume the request is from a legacy rogue client 
+     * using old internal header. See include/config/ftoption.h.
      */
-    if ( cmap_index >= 16 && !no_cmap_change )
+    if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE && !no_cmap_change )
     {
       FTC_OldCMapDesc  desc = (FTC_OldCMapDesc) face_id;
 
@@ -384,7 +376,7 @@
     /* something rotten can happen with rogue clients */
     if ( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first >=
                     FTC_CMAP_INDICES_MAX ) )
-      return 0;
+      return 0; /* XXX: should return appropriate error */
 
     gindex = FTC_CMAP_NODE( node )->indices[char_code -
                                             FTC_CMAP_NODE( node )->first];
@@ -400,6 +392,12 @@
                                       &face );
       if ( error )
         goto Exit;
+
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+      /* something rotten can happen with rogue clients */
+      if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE )
+        return 0; /* XXX: should return appropriate error */
+#endif
 
       if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
       {
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -879,6 +879,16 @@
         if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
           goto Exit;
 
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+        if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE )
+        {
+          FT_ERROR(( "cff_face_init: no Unicode cmap is found, "
+                     "and too many subtables (%d) to add synthesized cmap\n",
+                     nn ));
+          goto Exit;
+        }
+#endif
+
         /* we didn't find a Unicode charmap -- synthesize one */
         cmaprec.face        = cffface;
         cmaprec.platform_id = 3;
@@ -897,6 +907,15 @@
           cffface->charmap = cffface->charmaps[nn];
 
       Skip_Unicode:
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+        if ( nn > FT_MAX_CHARMAP_CACHEABLE )
+        {
+          FT_ERROR(( "cff_face_init: Unicode cmap is found, "
+                     "but too many preceding subtables (%d) to access\n",
+                     nn - 1 ));
+          goto Exit;
+        }
+#endif
         if ( encoding->count > 0 )
         {
           FT_CMap_Class  clazz;
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -3411,6 +3411,12 @@
     }
 
     num_cmaps = TT_NEXT_USHORT( p );
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+    if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE )
+      FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables(%d) "
+                 "subtable#%d and later are loaded but cannot be searched\n",
+                 num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 ));
+#endif
 
     for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
     {