Commit f11f3ed15b5987e52a201df57771a09307c305d2

Werner Lemberg 2021-08-18T06:54:34

[base] Fix ppem size overflow. Fixes #1086. * src/base/ftobjs.c (FT_Request_Metrics): Add return value. Check whether ppem values fit into unsigned short values. (FT_Request_Size): Updated. * include/freetype/internal/ftobjs.h: Updated. * src/cff/cffobjs.c (cff_size_request), src/cid/cidobjs.c (cid_size_request), src/truetype/ttdriver.c (tt_size_request), src/type1/t1objs.c (T1_Size_Request): Updated.

diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index 808eae8..e52a26a 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -673,7 +673,7 @@ FT_BEGIN_HEADER
 
 
   /* Set the metrics according to a size request. */
-  FT_BASE( void )
+  FT_BASE( FT_Error )
   FT_Request_Metrics( FT_Face          face,
                       FT_Size_Request  req );
 
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 5c1a4d0..342ac4a 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -3132,10 +3132,12 @@
   }
 
 
-  FT_BASE_DEF( void )
+  FT_BASE_DEF( FT_Error )
   FT_Request_Metrics( FT_Face          face,
                       FT_Size_Request  req )
   {
+    FT_Error  error = FT_Err_Ok;
+
     FT_Size_Metrics*  metrics;
 
 
@@ -3226,8 +3228,18 @@
         scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
       }
 
-      metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
-      metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
+      scaled_w = ( scaled_w + 32 ) >> 6;
+      scaled_h = ( scaled_h + 32 ) >> 6;
+      if ( scaled_w > FT_USHORT_MAX ||
+           scaled_h > FT_USHORT_MAX )
+      {
+        FT_ERROR(( "FT_Request_Metrics: Resulting ppem size too large\n" ));
+        error = FT_ERR( Invalid_Pixel_Size );
+        goto Exit;
+      }
+
+      metrics->x_ppem = (FT_UShort)scaled_w;
+      metrics->y_ppem = (FT_UShort)scaled_h;
 
       ft_recompute_scaled_metrics( face, metrics );
     }
@@ -3237,6 +3249,9 @@
       metrics->x_scale = 1L << 16;
       metrics->y_scale = 1L << 16;
     }
+
+  Exit:
+    return error;
   }
 
 
@@ -3300,7 +3315,7 @@
   FT_Request_Size( FT_Face          face,
                    FT_Size_Request  req )
   {
-    FT_Error         error = FT_Err_Ok;
+    FT_Error         error;
     FT_Driver_Class  clazz;
     FT_ULong         strike_index;
 
@@ -3336,13 +3351,15 @@
        */
       error = FT_Match_Size( face, req, 0, &strike_index );
       if ( error )
-        return error;
+        goto Exit;
 
       return FT_Select_Size( face, (FT_Int)strike_index );
     }
     else
     {
-      FT_Request_Metrics( face, req );
+      error = FT_Request_Metrics( face, req );
+      if ( error )
+        goto Exit;
 
       FT_TRACE5(( "FT_Request_Size:\n" ));
     }
@@ -3365,6 +3382,7 @@
     }
 #endif
 
+  Exit:
     return error;
   }
 
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index c502813..9b5b17c 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -283,6 +283,8 @@
   cff_size_request( FT_Size          size,
                     FT_Size_Request  req )
   {
+    FT_Error  error;
+
     CFF_Size           cffsize = (CFF_Size)size;
     PSH_Globals_Funcs  funcs;
 
@@ -304,7 +306,9 @@
 
 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
-    FT_Request_Metrics( size->face, req );
+    error = FT_Request_Metrics( size->face, req );
+    if ( error )
+      goto Exit;
 
     funcs = cff_size_get_globals_funcs( cffsize );
 
@@ -345,7 +349,8 @@
       }
     }
 
-    return FT_Err_Ok;
+  Exit:
+    return error;
   }
 
 
diff --git a/src/cid/cidobjs.c b/src/cid/cidobjs.c
index c756811..68ec84b 100644
--- a/src/cid/cidobjs.c
+++ b/src/cid/cidobjs.c
@@ -157,10 +157,14 @@
   cid_size_request( FT_Size          size,
                     FT_Size_Request  req )
   {
+    FT_Error  error;
+
     PSH_Globals_Funcs  funcs;
 
 
-    FT_Request_Metrics( size->face, req );
+    error = FT_Request_Metrics( size->face, req );
+    if ( error )
+      goto Exit;
 
     funcs = cid_size_get_globals_funcs( (CID_Size)size );
 
@@ -170,7 +174,8 @@
                         size->metrics.y_scale,
                         0, 0 );
 
-    return FT_Err_Ok;
+  Exit:
+    return error;
   }
 
 
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index eaa14aa..6fcfdb2 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -354,7 +354,16 @@
 
 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
-    FT_Request_Metrics( size->face, req );
+    {
+      FT_Error  err = FT_Request_Metrics( size->face, req );
+
+
+      if ( err )
+      {
+        error = err;
+        goto Exit;
+      }
+    }
 
     if ( FT_IS_SCALABLE( size->face ) )
     {
@@ -382,6 +391,7 @@
 #endif
     }
 
+  Exit:
     return error;
   }
 
diff --git a/src/type1/t1objs.c b/src/type1/t1objs.c
index ec202be..50dad03 100644
--- a/src/type1/t1objs.c
+++ b/src/type1/t1objs.c
@@ -116,11 +116,15 @@
   T1_Size_Request( FT_Size          t1size,     /* T1_Size */
                    FT_Size_Request  req )
   {
+    FT_Error  error;
+
     T1_Size            size  = (T1_Size)t1size;
     PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
 
 
-    FT_Request_Metrics( size->root.face, req );
+    error = FT_Request_Metrics( size->root.face, req );
+    if ( error )
+      goto Exit;
 
     if ( funcs )
       funcs->set_scale( (PSH_Globals)t1size->internal->module_data,
@@ -128,7 +132,8 @@
                         size->root.metrics.y_scale,
                         0, 0 );
 
-    return FT_Err_Ok;
+  Exit:
+    return error;
   }