Commit afaeeee9a04d0fae16bb4f844e81ca6e54bc93ef

Werner Lemberg 2013-05-04T14:05:24

Fix errors reported by clang's `sanitize' feature. * include/freetype/internal/ftstream.h: Simplify and fix integer extraction macros. (FT_INT8_, FT_BYTE_I16, FT_BYTE_I32, FT_INT8_I16, FT_INT8_I32, FT_INT8_I32, FT_INT8_U32): Removed. (FT_PEEK_SHORT, FT_PEEK_LONG, FT_PEEK_OFF3, FT_PEEK_SHORT_LE, FT_PEEK_LONG_LE, FT_PEEK_OFF3_LE): Use unsigned values for computations and convert to signed as the last step. * src/cff/cf2fixed.h (cf2_intToFixed, cf2_fixedToInt, cf2_fracToFixed): Avoid shifts of negative values. (cf2_intToFrac, cf2_fixedToFrac, cf2_fixedTo26Dot6): Removed, unused. * src/cff/cf2intrp.c (cf2_interpT2CharString) <cf2_cmdEXTENDEDNMBR, default>: Use unsigned values for computations and convert to signed as the last step. Use proper types in tracing messages. * src/cff/cffgload.c (cff_decoder_parse_charstrings): Use unsigned values for computation of operands and convert to signed as the last step. Use proper type in tracing message.

diff --git a/ChangeLog b/ChangeLog
index dad855f..abd34e3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2013-05-04  Werner Lemberg  <wl@gnu.org>
+
+	Fix errors reported by clang's `sanitize' feature.
+
+	* include/freetype/internal/ftstream.h: Simplify and fix integer
+	extraction macros.
+	(FT_INT8_, FT_BYTE_I16, FT_BYTE_I32, FT_INT8_I16, FT_INT8_I32,
+	FT_INT8_I32, FT_INT8_U32): Removed.
+	(FT_PEEK_SHORT, FT_PEEK_LONG, FT_PEEK_OFF3, FT_PEEK_SHORT_LE,
+	FT_PEEK_LONG_LE, FT_PEEK_OFF3_LE): Use unsigned values for
+	computations and convert to signed as the last step.
+
+	* src/cff/cf2fixed.h (cf2_intToFixed, cf2_fixedToInt,
+	cf2_fracToFixed): Avoid shifts of negative values.
+	(cf2_intToFrac, cf2_fixedToFrac, cf2_fixedTo26Dot6): Removed,
+	unused.
+
+	* src/cff/cf2intrp.c (cf2_interpT2CharString) <cf2_cmdEXTENDEDNMBR,
+	default>: Use unsigned values for computations and convert to signed
+	as the last step.
+	Use proper types in tracing messages.
+
+	* src/cff/cffgload.c (cff_decoder_parse_charstrings): Use unsigned
+	values for computation of operands and convert to signed as the last
+	step.
+	Use proper type in tracing message.
+
 2013-05-03  Werner Lemberg  <wl@gnu.org>
 
 	* src/cff/cf2blues.c: Remove dead code.
diff --git a/include/freetype/internal/ftstream.h b/include/freetype/internal/ftstream.h
index 8b18500..6c12d30 100644
--- a/include/freetype/internal/ftstream.h
+++ b/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Stream handling (specification).                                     */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004-2006, 2011 by                                */
+/*  Copyright 1996-2002, 2004-2006, 2011, 2013 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -154,67 +154,60 @@ FT_BEGIN_HEADER
   /*                                                                       */
 
 #define FT_BYTE_( p, i )  ( ((const FT_Byte*)(p))[(i)] )
-#define FT_INT8_( p, i )  ( ((const FT_Char*)(p))[(i)] )
 
 #define FT_INT16( x )   ( (FT_Int16)(x)  )
 #define FT_UINT16( x )  ( (FT_UInt16)(x) )
 #define FT_INT32( x )   ( (FT_Int32)(x)  )
 #define FT_UINT32( x )  ( (FT_UInt32)(x) )
 
-#define FT_BYTE_I16( p, i, s )  ( FT_INT16(  FT_BYTE_( p, i ) ) << (s) )
+
 #define FT_BYTE_U16( p, i, s )  ( FT_UINT16( FT_BYTE_( p, i ) ) << (s) )
-#define FT_BYTE_I32( p, i, s )  ( FT_INT32(  FT_BYTE_( p, i ) ) << (s) )
 #define FT_BYTE_U32( p, i, s )  ( FT_UINT32( FT_BYTE_( p, i ) ) << (s) )
 
-#define FT_INT8_I16( p, i, s )  ( FT_INT16(  FT_INT8_( p, i ) ) << (s) )
-#define FT_INT8_U16( p, i, s )  ( FT_UINT16( FT_INT8_( p, i ) ) << (s) )
-#define FT_INT8_I32( p, i, s )  ( FT_INT32(  FT_INT8_( p, i ) ) << (s) )
-#define FT_INT8_U32( p, i, s )  ( FT_UINT32( FT_INT8_( p, i ) ) << (s) )
-
 
-#define FT_PEEK_SHORT( p )  FT_INT16( FT_INT8_I16( p, 0, 8) | \
-                                      FT_BYTE_I16( p, 1, 0) )
+#define FT_PEEK_SHORT( p )  FT_INT16( FT_BYTE_U16( p, 0, 8) | \
+                                      FT_BYTE_U16( p, 1, 0) )
 
 #define FT_PEEK_USHORT( p )  FT_UINT16( FT_BYTE_U16( p, 0, 8 ) | \
                                         FT_BYTE_U16( p, 1, 0 ) )
 
-#define FT_PEEK_LONG( p )  FT_INT32( FT_INT8_I32( p, 0, 24 ) | \
-                                     FT_BYTE_I32( p, 1, 16 ) | \
-                                     FT_BYTE_I32( p, 2,  8 ) | \
-                                     FT_BYTE_I32( p, 3,  0 ) )
+#define FT_PEEK_LONG( p )  FT_INT32( FT_BYTE_U32( p, 0, 24 ) | \
+                                     FT_BYTE_U32( p, 1, 16 ) | \
+                                     FT_BYTE_U32( p, 2,  8 ) | \
+                                     FT_BYTE_U32( p, 3,  0 ) )
 
 #define FT_PEEK_ULONG( p )  FT_UINT32( FT_BYTE_U32( p, 0, 24 ) | \
                                        FT_BYTE_U32( p, 1, 16 ) | \
                                        FT_BYTE_U32( p, 2,  8 ) | \
                                        FT_BYTE_U32( p, 3,  0 ) )
 
-#define FT_PEEK_OFF3( p )  FT_INT32( FT_INT8_I32( p, 0, 16 ) | \
-                                     FT_BYTE_I32( p, 1,  8 ) | \
-                                     FT_BYTE_I32( p, 2,  0 ) )
+#define FT_PEEK_OFF3( p )  FT_INT32( FT_BYTE_U32( p, 0, 16 ) | \
+                                     FT_BYTE_U32( p, 1,  8 ) | \
+                                     FT_BYTE_U32( p, 2,  0 ) )
 
 #define FT_PEEK_UOFF3( p )  FT_UINT32( FT_BYTE_U32( p, 0, 16 ) | \
                                        FT_BYTE_U32( p, 1,  8 ) | \
                                        FT_BYTE_U32( p, 2,  0 ) )
 
-#define FT_PEEK_SHORT_LE( p )  FT_INT16( FT_INT8_I16( p, 1, 8 ) | \
-                                         FT_BYTE_I16( p, 0, 0 ) )
+#define FT_PEEK_SHORT_LE( p )  FT_INT16( FT_BYTE_U16( p, 1, 8 ) | \
+                                         FT_BYTE_U16( p, 0, 0 ) )
 
 #define FT_PEEK_USHORT_LE( p )  FT_UINT16( FT_BYTE_U16( p, 1, 8 ) |  \
                                            FT_BYTE_U16( p, 0, 0 ) )
 
-#define FT_PEEK_LONG_LE( p )  FT_INT32( FT_INT8_I32( p, 3, 24 ) | \
-                                        FT_BYTE_I32( p, 2, 16 ) | \
-                                        FT_BYTE_I32( p, 1,  8 ) | \
-                                        FT_BYTE_I32( p, 0,  0 ) )
+#define FT_PEEK_LONG_LE( p )  FT_INT32( FT_BYTE_U32( p, 3, 24 ) | \
+                                        FT_BYTE_U32( p, 2, 16 ) | \
+                                        FT_BYTE_U32( p, 1,  8 ) | \
+                                        FT_BYTE_U32( p, 0,  0 ) )
 
 #define FT_PEEK_ULONG_LE( p )  FT_UINT32( FT_BYTE_U32( p, 3, 24 ) | \
                                           FT_BYTE_U32( p, 2, 16 ) | \
                                           FT_BYTE_U32( p, 1,  8 ) | \
                                           FT_BYTE_U32( p, 0,  0 ) )
 
-#define FT_PEEK_OFF3_LE( p )  FT_INT32( FT_INT8_I32( p, 2, 16 ) | \
-                                        FT_BYTE_I32( p, 1,  8 ) | \
-                                        FT_BYTE_I32( p, 0,  0 ) )
+#define FT_PEEK_OFF3_LE( p )  FT_INT32( FT_BYTE_U32( p, 2, 16 ) | \
+                                        FT_BYTE_U32( p, 1,  8 ) | \
+                                        FT_BYTE_U32( p, 0,  0 ) )
 
 #define FT_PEEK_UOFF3_LE( p )  FT_UINT32( FT_BYTE_U32( p, 2, 16 ) | \
                                           FT_BYTE_U32( p, 1,  8 ) | \
diff --git a/src/cff/cf2fixed.h b/src/cff/cf2fixed.h
index ef5915e..ed1452a 100644
--- a/src/cff/cf2fixed.h
+++ b/src/cff/cf2fixed.h
@@ -54,28 +54,26 @@ FT_BEGIN_HEADER
 #define CF2_FIXED_ONE      0x10000L
 #define CF2_FIXED_EPSILON  0x0001
 
-#define cf2_intToFixed( i )                                 \
-          ( (i) << 16 )
-#define cf2_fixedToInt( x )                                 \
-          ( ( (x) + 0x8000 ) >> 16 )
-#define cf2_fixedRound( x )                                 \
+  /* in C 89, left and right shift of negative numbers is  */
+  /* implementation specific behaviour in the general case */
+
+#define cf2_intToFixed( i )                                    \
+          ( (CF2_Fixed)( (FT_UInt32)(i) << 16 ) )
+#define cf2_fixedToInt( x )                                    \
+          ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
+#define cf2_fixedRound( x )                                    \
           ( (CF2_Fixed)( ( (x) + 0x8000 ) & 0xFFFF0000L ) )
-#define cf2_floatToFixed( f )                               \
+#define cf2_floatToFixed( f )                                  \
           ( (CF2_Fixed)( (f) * 65536.0 + 0.5 ) )
-#define cf2_fixedAbs( x )                                   \
+#define cf2_fixedAbs( x )                                      \
           ( (x) < 0 ? -(x) : (x) )
-#define cf2_fixedFloor( x )                                 \
-          ( (CF2_Fixed)((x) & 0xFFFF0000L ) )
-#define cf2_fixedFraction( x )                              \
+#define cf2_fixedFloor( x )                                    \
+          ( (CF2_Fixed)( (x) & 0xFFFF0000L ) )
+#define cf2_fixedFraction( x )                                 \
           ( (x) - cf2_fixedFloor( x ) )
-#define cf2_fracToFixed( x )                                \
-          ( ( (x) + 0x2000 ) >> 14 )
-#define cf2_intToFrac( i )                                  \
-          ( (i) << 30 )
-#define cf2_fixedToFrac( x )                                \
-          ( (x) << 14 )
-#define cf2_fixedTo26Dot6( x )                              \
-          ( ( (x) + 0x200 ) >> 10 )
+#define cf2_fracToFixed( x )                                   \
+          ( (x) < 0 ? -( ( -(x) + 0x2000 ) >> 14 )             \
+                    :  ( (  (x) + 0x2000 ) >> 14 ) )
 
 
   /* signed numeric types */
diff --git a/src/cff/cf2intrp.c b/src/cff/cf2intrp.c
index 0c2d612..6814f64 100644
--- a/src/cff/cf2intrp.c
+++ b/src/cff/cf2intrp.c
@@ -1394,10 +1394,8 @@
           CF2_Int  v;
 
 
-          /* sign-extend first byte */
-          v   = (FT_Char)cf2_buf_readByte( charstring );
-          v <<= 8;
-          v  += cf2_buf_readByte( charstring );
+          v = (FT_Short)( ( cf2_buf_readByte( charstring ) << 8 ) |
+                            cf2_buf_readByte( charstring )        );
 
           FT_TRACE4(( " %d", v ));
 
@@ -1408,56 +1406,65 @@
       default:
         /* numbers */
         {
-          CF2_Int  v;
-
-
           if ( /* op1 >= 32 && */ op1 <= 246 )
           {
-            FT_TRACE4(( " %d", op1 - 139 ));
+            CF2_Int  v;
+
+
+            v = op1 - 139;
+
+            FT_TRACE4(( " %d", v ));
 
             /* -107 .. 107 */
-            cf2_stack_pushInt( opStack, op1 - 139 );
+            cf2_stack_pushInt( opStack, v );
           }
 
           else if ( /* op1 >= 247 && */ op1 <= 250 )
           {
+            CF2_Int  v;
+
+
             v  = op1;
             v -= 247;
             v *= 256;
             v += cf2_buf_readByte( charstring );
+            v += 108;
 
-            FT_TRACE4(( " %ld", v + 108 ));
+            FT_TRACE4(( " %d", v ));
 
             /* 108 .. 1131 */
-            cf2_stack_pushInt( opStack, v + 108 );
+            cf2_stack_pushInt( opStack, v );
           }
 
           else if ( /* op1 >= 251 && */ op1 <= 254 )
           {
+            CF2_Int  v;
+
+
             v  = op1;
             v -= 251;
             v *= 256;
             v += cf2_buf_readByte( charstring );
+            v  = -v - 108;
 
-            FT_TRACE4(( " %ld", -v - 108 ));
+            FT_TRACE4(( " %d", v ));
 
             /* -1131 .. -108 */
-            cf2_stack_pushInt( opStack, -v - 108 );
+            cf2_stack_pushInt( opStack, v );
           }
 
           else /* op1 == 255 */
           {
-            v  = cf2_buf_readByte( charstring );
-            v *= 256;
-            v += cf2_buf_readByte( charstring );
-            v *= 256;
-            v += cf2_buf_readByte( charstring );
-            v *= 256;
-            v += cf2_buf_readByte( charstring );
+            CF2_Fixed  v;
+
+
+            v = (CF2_Fixed)( ( cf2_buf_readByte( charstring ) << 24 ) |
+                             ( cf2_buf_readByte( charstring ) << 16 ) |
+                             ( cf2_buf_readByte( charstring ) <<  8 ) |
+                               cf2_buf_readByte( charstring )         );
 
             FT_TRACE4(( " %.2f", v / 65536.0 ));
 
-            /* interpret the value as a CF2_Fixed */
             cf2_stack_pushFixed( opStack, v );
           }
         }
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index fc01d98..9a15107 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -968,11 +968,14 @@
 
 
         /* this is an operand, push it on the stack */
+
+        /* if we use shifts, all computations are done with unsigned */
+        /* values; the conversion to a signed value is the last step */
         if ( v == 28 )
         {
           if ( ip + 1 >= limit )
             goto Syntax_Error;
-          val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
+          val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] );
           ip += 2;
         }
         else if ( v < 247 )
@@ -993,10 +996,10 @@
         {
           if ( ip + 3 >= limit )
             goto Syntax_Error;
-          val = ( (FT_Int32)ip[0] << 24 ) |
-                ( (FT_Int32)ip[1] << 16 ) |
-                ( (FT_Int32)ip[2] <<  8 ) |
-                            ip[3];
+          val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
+                            ( (FT_UInt32)ip[1] << 16 ) |
+                            ( (FT_UInt32)ip[2] <<  8 ) |
+                              (FT_UInt32)ip[3] );
           ip    += 4;
           if ( charstring_type == 2 )
             shift = 0;
@@ -1004,12 +1007,12 @@
         if ( decoder->top - stack >= CFF_MAX_OPERANDS )
           goto Stack_Overflow;
 
-        val           <<= shift;
+        val             = (FT_Int32)( (FT_UInt32)val << shift );
         *decoder->top++ = val;
 
 #ifdef FT_DEBUG_LEVEL_TRACE
         if ( !( val & 0xFFFFL ) )
-          FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) ));
+          FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) ));
         else
           FT_TRACE4(( " %.2f", val / 65536.0 ));
 #endif