From afaeeee9a04d0fae16bb4f844e81ca6e54bc93ef Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Sat, 4 May 2013 14:05:24 +0200 Subject: [PATCH] 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) : 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. --- ChangeLog | 27 +++++++++++++++ include/freetype/internal/ftstream.h | 47 ++++++++++++-------------- src/cff/cf2fixed.h | 34 +++++++++---------- src/cff/cf2intrp.c | 49 ++++++++++++++++------------ src/cff/cffgload.c | 17 ++++++---- 5 files changed, 101 insertions(+), 73 deletions(-) diff --git a/ChangeLog b/ChangeLog index dad855fbf..abd34e3bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2013-05-04 Werner Lemberg + + 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) : 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 * src/cff/cf2blues.c: Remove dead code. diff --git a/include/freetype/internal/ftstream.h b/include/freetype/internal/ftstream.h index 8b185005f..6c12d30e4 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 ef5915e3e..ed1452a7d 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 0c2d61228..6814f6465 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 fc01d98a1..9a151071a 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