shithub: freetype+ttf2subf

Download patch

ref: e942a31007ae695c218270027f2cec03ac0c79cd
parent: c350aac0997d0ce0d8550dbd79bc8da644a4b163
author: Alexei Podtelezhnikov <apodtele@gmail.com>
date: Thu Sep 9 18:17:46 EDT 2021

[truetype] Tweak `loca` clamping.

Fixes #1095.

* src/truetype/ttpload.c (tt_face_load_loca): Fix up clamping.
* include/freetype/internal/tttypes.h (TT_Face): Correct docs.

git/fs: mount .git/fs: mount/attach disallowed
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -1372,7 +1372,7 @@
    *
    *   num_locations ::
    *     The number of glyph locations in this TrueType file.  This should be
-   *     identical to the number of glyphs.  Ignored for Type 2 fonts.
+   *     one more than the number of glyphs.  Ignored for Type 2 fonts.
    *
    *   glyph_locations ::
    *     An array of longs.  These are offsets to glyph data within the
@@ -1598,7 +1598,7 @@
     FT_ULong              horz_metrics_size;
     FT_ULong              vert_metrics_size;
 
-    FT_ULong              num_locations; /* in broken TTF, gid > 0xFFFF */
+    FT_ULong              num_locations; /* up to 0xFFFF + 1 */
     FT_Byte*              glyph_locations;
 
     FT_Byte*              hdmx_table;
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -98,29 +98,16 @@
       goto Exit;
     }
 
-    if ( face->header.Index_To_Loc_Format != 0 )
-    {
-      shift = 2;
+    shift = face->header.Index_To_Loc_Format != 0 ? 2 : 1;
 
-      if ( table_len >= 0x40000L )
-      {
-        FT_TRACE2(( "table too large\n" ));
-        table_len = 0x3FFFFL;
-      }
-      face->num_locations = table_len >> shift;
-    }
-    else
+    if ( table_len > 0x10000UL << shift )
     {
-      shift = 1;
-
-      if ( table_len >= 0x20000L )
-      {
-        FT_TRACE2(( "table too large\n" ));
-        table_len = 0x1FFFFL;
-      }
-      face->num_locations = table_len >> shift;
+      FT_TRACE2(( "table too large\n" ));
+      table_len = 0x10000UL << shift;
     }
 
+    face->num_locations = table_len >> shift;
+
     if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
     {
       FT_TRACE2(( "glyph count mismatch!  loca: %ld, maxp: %ld\n",
@@ -127,7 +114,7 @@
                   face->num_locations - 1, face->root.num_glyphs ));
 
       /* we only handle the case where `maxp' gives a larger value */
-      if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
+      if ( face->num_locations < (FT_ULong)face->root.num_glyphs + 1 )
       {
         FT_ULong  new_loca_len =
                     ( (FT_ULong)face->root.num_glyphs + 1 ) << shift;