Commit 94ebc248653ede802b2bfbf6219e17f487fab3ff

Werner Lemberg 2019-05-12T21:05:36

[truetype] Doh. Fix last commit to make it work. Very embarassing :-) Reported as https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14701 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14705 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14710 * src/truetype/ttgload.c (IS_DEFAULT_INSTANCE): Move up and add argument; update all callers. (TT_Process_Simple_Glyph): Use it. The `unrounded' array is active for variation fonts only, thus also enclose related code with `#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT ... #endif' where necessary. Revert commit a113e5d from 2019-05-09, and don't use `extra_points2' but allocate a temporary array. Speed up the scaling of the `unrounded' array. * src/truetype/ttgxvar.c (FT_fixedToInt, FT_FixedToFdot6): Fix type conversions and rounding. The unsigned type must have more or equal bits to the signed type.

diff --git a/ChangeLog b/ChangeLog
index 52492cd..77766c4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,34 @@
+2019-05-12  Werner Lemberg  <wl@gnu.org>
+
+	[truetype] Doh.  Fix last commit to make it work.
+
+	Very embarassing :-)
+
+	Reported as
+
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14701
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14705
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14710
+
+	* src/truetype/ttgload.c (IS_DEFAULT_INSTANCE): Move up and add
+	argument; update all callers.
+	(TT_Process_Simple_Glyph): Use it.  The `unrounded' array is active
+	for variation fonts only, thus also enclose related code with
+	`#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT ...  #endif' where
+	necessary.
+	Revert commit a113e5d from 2019-05-09, and don't use `extra_points2'
+	but allocate a temporary array.
+	Speed up the scaling of the `unrounded' array.
+
+	* src/truetype/ttgxvar.c (FT_fixedToInt, FT_FixedToFdot6): Fix type
+	conversions and rounding.  The unsigned type must have more or equal
+	bits to the signed type.
+
 2019-05-09  Werner Lemberg  <wl@gnu.org>
 
 	[truetype] Increase precision of font variation (#54371).
 
-	This patch make FreeType use font units in 26.6 format internally
+	This patch makes FreeType use font units in 26.6 format internally
 	instead of integers.
 
 	* src/truetype/ttgxvar.c (FT_fixedToFdot6): New macro.
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index d4a87ef..0111c40 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -82,6 +82,15 @@
 #define UNSCALED_COMPONENT_OFFSET  0x1000
 
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#define IS_DEFAULT_INSTANCE( _face )             \
+          ( !( FT_IS_NAMED_INSTANCE( _face ) ||  \
+               FT_IS_VARIATION( _face )      ) )
+#else
+#define IS_DEFAULT_INSTANCE( _face )  1
+#endif
+
+
   /**************************************************************************
    *
    * Return the horizontal metrics in font units for a given glyph.
@@ -925,9 +934,13 @@
     FT_GlyphLoader  gloader = loader->gloader;
     FT_Error        error   = FT_Err_Ok;
     FT_Outline*     outline;
-    FT_Vector*      unrounded;
     FT_Int          n_points;
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+    FT_Memory   memory    = loader->face->root.memory;
+    FT_Vector*  unrounded = NULL;
+#endif
+
 
     outline  = &gloader->current.outline;
     n_points = outline->n_points;
@@ -948,12 +961,12 @@
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
-    if ( FT_IS_NAMED_INSTANCE( FT_FACE( loader->face ) ) ||
-         FT_IS_VARIATION( FT_FACE( loader->face ) )      )
+    if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
     {
-      /* Deltas apply to the unscaled data.                           */
-      /* We temporarily use `extra_points2' to hold unrounded values. */
-      unrounded = gloader->current.extra_points2;
+      if ( FT_NEW_ARRAY( unrounded, n_points ) )
+        goto Exit;
+
+      /* Deltas apply to the unscaled data. */
       error = TT_Vary_Apply_Glyph_Deltas( loader->face,
                                           loader->glyph_index,
                                           outline,
@@ -973,11 +986,19 @@
                                          unrounded[n_points - 2].x ) / 64;
 
       if ( error )
-        return error;
+        goto Exit;
     }
 
 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
 
+    if ( IS_HINTED( loader->load_flags ) )
+    {
+      tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
+
+      FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
+                     loader->zone.n_points + 4 );
+    }
+
     {
 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
       TT_Face    face   = loader->face;
@@ -1021,15 +1042,21 @@
           /* the amount was determined via experimentation */
           if ( x_scale_factor != 1000 && ppem > 11 )
           {
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
             FT_Vector*  orig_points = outline->points;
 
 
-            outline->points = unrounded;
+            if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
+              outline->points = unrounded;
+#endif
             FT_Outline_EmboldenXY( outline,
                                    FT_MulFix( 1280 * ppem,
                                               1000 - x_scale_factor ),
                                    0 );
-            outline->points = orig_points;
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+            if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
+              outline->points = orig_points;
+#endif
           }
           do_scale = TRUE;
         }
@@ -1051,10 +1078,29 @@
 
       if ( do_scale )
       {
-        for ( ; vec < limit; vec++, unrounded++ )
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+        if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
         {
-          vec->x = FT_MulDiv( unrounded->x, x_scale, 0x10000L * 64 );
-          vec->y = FT_MulDiv( unrounded->y, y_scale, 0x10000L * 64 );
+          FT_Vector*  u = unrounded;
+
+          FT_Fixed  xs = x_scale >> 6;
+          FT_Fixed  ys = y_scale >> 6;
+
+
+          for ( ; vec < limit; vec++, u++ )
+          {
+            vec->x = FT_MulFix( u->x, xs );
+            vec->y = FT_MulFix( u->y, ys );
+          }
+        }
+        else
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+        {
+          for ( ; vec < limit; vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
         }
       }
 
@@ -1081,16 +1127,16 @@
 
     if ( IS_HINTED( loader->load_flags ) )
     {
-      tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
-
-      FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
-                     loader->zone.n_points + 4 );
-
       loader->zone.n_points += 4;
 
       error = TT_Hint_Glyph( loader, 0 );
     }
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+  Exit:
+    FT_FREE( unrounded );
+#endif
+
     return error;
   }
 
@@ -2742,13 +2788,6 @@
     FT_Error      error;
     TT_LoaderRec  loader;
 
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-#define IS_DEFAULT_INSTANCE  ( !( FT_IS_NAMED_INSTANCE( glyph->face ) ||  \
-                                  FT_IS_VARIATION( glyph->face )      ) )
-#else
-#define IS_DEFAULT_INSTANCE  1
-#endif
-
 
     FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
 
@@ -2757,7 +2796,7 @@
     /* try to load embedded bitmap (if any) */
     if ( size->strike_index != 0xFFFFFFFFUL      &&
          ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
-         IS_DEFAULT_INSTANCE                     )
+         IS_DEFAULT_INSTANCE( glyph->face )      )
     {
       FT_Fixed  x_scale = size->root.metrics.x_scale;
       FT_Fixed  y_scale = size->root.metrics.y_scale;
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 317340a..eab4239 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -72,10 +72,10 @@
           ( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
 #define FT_intToFixed( i )                      \
           ( (FT_Fixed)( (FT_ULong)(i) << 16 ) )
-#define FT_fixedToInt( x )                                     \
-          ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
+#define FT_fixedToInt( x )                                    \
+          ( (FT_Short)( ( (FT_ULong)(x) + 0x8000U ) >> 16 ) )
 #define FT_fixedToFdot6( x )                              \
-          ( (FT_Pos)( ( (FT_UInt32)(x) + 0x20 ) >> 10 ) )
+          ( (FT_Pos)( ( (FT_ULong)(x) + 0x200 ) >> 10 ) )
 
 
   /**************************************************************************