Commit 8c8f51c55813b4f01e1a77d4fc8838c6a5fb998c

Werner Lemberg 2021-11-19T21:50:22

Avoid undefined left-shifts. We really have to use double casts to avoid issues with C's and C++'s signedness propagation rules in implicit casts. Reported as https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=41178 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=41182 * include/freetype/config/public-macros.h (FT_STATIC_CAST, FT_REINTERPRET_CAST): Modify macro to take two arguments. Update all callers. (FT_STATIC_BYTE_CAST): New macro. * include/freetype/freetype.h (FT_ENC_TAG): Use `FT_STATIC_BYTE_CAST`. * include/freetype/ftimage.h (FT_IMAGE_TAG): Ditto. * include/freetype/fttypes.h (FT_MAKE_TAG): Ditto. Use `FT_Tag` for casting. * src/ftraster/ftmisc.h (FT_MAKE_TAG): Removed, no longer needed. (FT_STATIC_BYTE_CAST): New macro. * src/smooth/ftgrays.c (FT_STATIC_CAST): Replace with... (FT_STATIC_BYTE_CAST): ... this.

diff --git a/include/freetype/config/public-macros.h b/include/freetype/config/public-macros.h
index 1b03640..9fbb327 100644
--- a/include/freetype/config/public-macros.h
+++ b/include/freetype/config/public-macros.h
@@ -120,11 +120,16 @@ FT_BEGIN_HEADER
    * Support for casts in both C and C++.
    */
 #ifdef __cplusplus
-#define FT_STATIC_CAST( type )       static_cast<type>
-#define FT_REINTERPRET_CAST( type )  reinterpret_cast<type>
+#define FT_STATIC_CAST( type, var )       static_cast<type>(var)
+#define FT_REINTERPRET_CAST( type, var )  reinterpret_cast<type>(var)
+
+#define FT_STATIC_BYTE_CAST( type, var )                         \
+          static_cast<type>( static_cast<unsigned char>( var ) )
 #else
-#define FT_STATIC_CAST( type )       (type)
-#define FT_REINTERPRET_CAST( type )  (type)
+#define FT_STATIC_CAST( type, var )       (type)(var)
+#define FT_REINTERPRET_CAST( type, var )  (type)(var)
+
+#define FT_STATIC_BYTE_CAST( type, var )  (type)(unsigned char)(var)
 #endif
 
 
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index 7da4eb6..e3438f2 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -617,11 +617,11 @@ FT_BEGIN_HEADER
 
 #ifndef FT_ENC_TAG
 
-#define FT_ENC_TAG( value, a, b, c, d )                      \
-          value = ( ( FT_STATIC_CAST( FT_Byte )(a) << 24 ) | \
-                    ( FT_STATIC_CAST( FT_Byte )(b) << 16 ) | \
-                    ( FT_STATIC_CAST( FT_Byte )(c) <<  8 ) | \
-                      FT_STATIC_CAST( FT_Byte )(d)         )
+#define FT_ENC_TAG( value, a, b, c, d )                             \
+          value = ( ( FT_STATIC_BYTE_CAST( FT_UInt32, a ) << 24 ) | \
+                    ( FT_STATIC_BYTE_CAST( FT_UInt32, b ) << 16 ) | \
+                    ( FT_STATIC_BYTE_CAST( FT_UInt32, c ) <<  8 ) | \
+                      FT_STATIC_BYTE_CAST( FT_UInt32, d )         )
 
 #endif /* FT_ENC_TAG */
 
@@ -3182,7 +3182,7 @@ FT_BEGIN_HEADER
    *   necessary to empty the cache after a mode switch to avoid false hits.
    *
    */
-#define FT_LOAD_TARGET_( x )   ( FT_STATIC_CAST( FT_Int32 )( (x) & 15 ) << 16 )
+#define FT_LOAD_TARGET_( x )   ( FT_STATIC_CAST( FT_Int32, (x) & 15 ) << 16 )
 
 #define FT_LOAD_TARGET_NORMAL  FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL )
 #define FT_LOAD_TARGET_LIGHT   FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT  )
@@ -3201,8 +3201,8 @@ FT_BEGIN_HEADER
    *   @FT_LOAD_TARGET_XXX value.
    *
    */
-#define FT_LOAD_TARGET_MODE( x )                                 \
-          FT_STATIC_CAST( FT_Render_Mode )( ( (x) >> 16 ) & 15 )
+#define FT_LOAD_TARGET_MODE( x )                               \
+          FT_STATIC_CAST( FT_Render_Mode, ( (x) >> 16 ) & 15 )
 
 
   /**************************************************************************
diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h
index 6e33520..88533b8 100644
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -696,11 +696,11 @@ FT_BEGIN_HEADER
    */
 #ifndef FT_IMAGE_TAG
 
-#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 )                      \
-          value = ( ( FT_STATIC_CAST( unsigned char )( _x1 ) << 24 ) | \
-                    ( FT_STATIC_CAST( unsigned char )( _x2 ) << 16 ) | \
-                    ( FT_STATIC_CAST( unsigned char )( _x3 ) << 8  ) | \
-                      FT_STATIC_CAST( unsigned char )( _x4 )         )
+#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 )                         \
+          value = ( ( FT_STATIC_BYTE_CAST( unsigned long, _x1 ) << 24 ) | \
+                    ( FT_STATIC_BYTE_CAST( unsigned long, _x2 ) << 16 ) | \
+                    ( FT_STATIC_BYTE_CAST( unsigned long, _x3 ) << 8  ) | \
+                      FT_STATIC_BYTE_CAST( unsigned long, _x4 )         )
 
 #endif /* FT_IMAGE_TAG */
 
diff --git a/include/freetype/ftmodapi.h b/include/freetype/ftmodapi.h
index 9d6c1b3..b77d356 100644
--- a/include/freetype/ftmodapi.h
+++ b/include/freetype/ftmodapi.h
@@ -347,9 +347,9 @@ FT_BEGIN_HEADER
    *   2.11
    *
    */
-#define FT_FACE_DRIVER_NAME( face )                     \
-          ( ( *FT_REINTERPRET_CAST( FT_Module_Class** ) \
-                 ( ( face )->driver ) )->module_name )
+#define FT_FACE_DRIVER_NAME( face )                                     \
+          ( ( *FT_REINTERPRET_CAST( FT_Module_Class**,                  \
+                                    ( face )->driver ) )->module_name )
 
 
   /**************************************************************************
diff --git a/include/freetype/fttypes.h b/include/freetype/fttypes.h
index 3b23358..eb7c472 100644
--- a/include/freetype/fttypes.h
+++ b/include/freetype/fttypes.h
@@ -479,18 +479,19 @@ FT_BEGIN_HEADER
    *
    * @description:
    *   This macro converts four-letter tags that are used to label TrueType
-   *   tables into an unsigned long, to be used within FreeType.
+   *   tables into an `FT_Tag` type, to be used within FreeType.
    *
    * @note:
    *   The produced values **must** be 32-bit integers.  Don't redefine this
    *   macro.
    */
-#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 )                \
-          FT_STATIC_CAST( FT_Tag )                       \
-          ( ( FT_STATIC_CAST( FT_Byte )( _x1 ) << 24 ) | \
-            ( FT_STATIC_CAST( FT_Byte )( _x2 ) << 16 ) | \
-            ( FT_STATIC_CAST( FT_Byte )( _x3 ) <<  8 ) | \
-              FT_STATIC_CAST( FT_Byte )( _x4 )         )
+#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 )                      \
+          FT_STATIC_CAST(                                      \
+            FT_Tag,                                            \
+            ( ( FT_STATIC_BYTE_CAST( FT_Tag, _x1 ) << 24 ) |   \
+              ( FT_STATIC_BYTE_CAST( FT_Tag, _x2 ) << 16 ) |   \
+              ( FT_STATIC_BYTE_CAST( FT_Tag, _x3 ) <<  8 ) |   \
+                FT_STATIC_BYTE_CAST( FT_Tag, _x4 )         ) )
 
 
   /*************************************************************************/
@@ -588,7 +589,7 @@ FT_BEGIN_HEADER
 
 
 #define FT_IS_EMPTY( list )  ( (list).head == 0 )
-#define FT_BOOL( x )         FT_STATIC_CAST( FT_Bool )( (x) != 0 )
+#define FT_BOOL( x )         FT_STATIC_CAST( FT_Bool, (x) != 0 )
 
   /* concatenate C tokens */
 #define FT_ERR_XCAT( x, y )  x ## y
diff --git a/src/raster/ftmisc.h b/src/raster/ftmisc.h
index 9de0b12..b12a051 100644
--- a/src/raster/ftmisc.h
+++ b/src/raster/ftmisc.h
@@ -47,11 +47,8 @@
   typedef signed long    FT_F26Dot6;
   typedef int            FT_Error;
 
-#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
-          ( ( (FT_ULong)_x1 << 24 ) |     \
-            ( (FT_ULong)_x2 << 16 ) |     \
-            ( (FT_ULong)_x3 <<  8 ) |     \
-              (FT_ULong)_x4         )
+
+#define FT_STATIC_BYTE_CAST( type, var )  (type)(FT_Byte)(var)
 
 
   /* from include/freetype/ftsystem.h */
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 37f4fe0..8235a94 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -152,7 +152,7 @@
 #define ADD_INT( a, b )                                  \
           (int)( (unsigned int)(a) + (unsigned int)(b) )
 
-#define FT_STATIC_CAST( type )  (type)
+#define FT_STATIC_BYTE_CAST( type, var )  (type)(unsigned char)(var)
 
 
 #define ft_memset   memset