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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
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