| Index: src/psaux/psconv.c
|
| diff --git a/src/psaux/psconv.c b/src/psaux/psconv.c
|
| index 9ea7fb988801847688e2437f6491408f41e52820..d0d8861c22f0aa1e00faee48c163edd84938048b 100644
|
| --- a/src/psaux/psconv.c
|
| +++ b/src/psaux/psconv.c
|
| @@ -4,7 +4,7 @@
|
| /* */
|
| /* Some convenience conversions (body). */
|
| /* */
|
| -/* Copyright 2006, 2008, 2009, 2012 by */
|
| +/* Copyright 2006, 2008, 2009, 2012-2013 by */
|
| /* David Turner, Robert Wilhelm, and Werner Lemberg. */
|
| /* */
|
| /* This file is part of the FreeType project, and may only be used, */
|
| @@ -18,11 +18,22 @@
|
|
|
| #include <ft2build.h>
|
| #include FT_INTERNAL_POSTSCRIPT_AUX_H
|
| +#include FT_INTERNAL_DEBUG_H
|
|
|
| #include "psconv.h"
|
| #include "psauxerr.h"
|
|
|
|
|
| + /*************************************************************************/
|
| + /* */
|
| + /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
|
| + /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
|
| + /* messages during execution. */
|
| + /* */
|
| +#undef FT_COMPONENT
|
| +#define FT_COMPONENT trace_psconv
|
| +
|
| +
|
| /* The following array is used by various functions to quickly convert */
|
| /* digits (both decimal and non-decimal) into numbers. */
|
|
|
| @@ -69,18 +80,29 @@
|
| #endif /* 'A' == 193 */
|
|
|
|
|
| - FT_LOCAL_DEF( FT_Int )
|
| + FT_LOCAL_DEF( FT_Long )
|
| PS_Conv_Strtol( FT_Byte** cursor,
|
| FT_Byte* limit,
|
| - FT_Int base )
|
| + FT_Long base )
|
| {
|
| FT_Byte* p = *cursor;
|
| - FT_Int num = 0;
|
| - FT_Bool sign = 0;
|
|
|
| + FT_Long num = 0;
|
| + FT_Bool sign = 0;
|
| + FT_Bool have_overflow = 0;
|
| +
|
| + FT_Long num_limit;
|
| + FT_Char c_limit;
|
| +
|
| +
|
| + if ( p >= limit )
|
| + goto Bad;
|
|
|
| - if ( p >= limit || base < 2 || base > 36 )
|
| + if ( base < 2 || base > 36 )
|
| + {
|
| + FT_TRACE4(( "!!!INVALID BASE:!!!" ));
|
| return 0;
|
| + }
|
|
|
| if ( *p == '-' || *p == '+' )
|
| {
|
| @@ -88,9 +110,12 @@
|
|
|
| p++;
|
| if ( p == limit )
|
| - return 0;
|
| + goto Bad;
|
| }
|
|
|
| + num_limit = 0x7FFFFFFFL / base;
|
| + c_limit = (FT_Char)( 0x7FFFFFFFL % base );
|
| +
|
| for ( ; p < limit; p++ )
|
| {
|
| FT_Char c;
|
| @@ -104,54 +129,84 @@
|
| if ( c < 0 || c >= base )
|
| break;
|
|
|
| - num = num * base + c;
|
| + if ( num > num_limit || ( num == num_limit && c > c_limit ) )
|
| + have_overflow = 1;
|
| + else
|
| + num = num * base + c;
|
| + }
|
| +
|
| + *cursor = p;
|
| +
|
| + if ( have_overflow )
|
| + {
|
| + num = 0x7FFFFFFFL;
|
| + FT_TRACE4(( "!!!OVERFLOW:!!!" ));
|
| }
|
|
|
| if ( sign )
|
| num = -num;
|
|
|
| - *cursor = p;
|
| -
|
| return num;
|
| +
|
| + Bad:
|
| + FT_TRACE4(( "!!!END OF DATA:!!!" ));
|
| + return 0;
|
| }
|
|
|
|
|
| - FT_LOCAL_DEF( FT_Int )
|
| + FT_LOCAL_DEF( FT_Long )
|
| PS_Conv_ToInt( FT_Byte** cursor,
|
| FT_Byte* limit )
|
|
|
| {
|
| - FT_Byte* p;
|
| - FT_Int num;
|
| + FT_Byte* p = *cursor;
|
| + FT_Byte* curp;
|
| +
|
| + FT_Long num;
|
|
|
|
|
| - num = PS_Conv_Strtol( cursor, limit, 10 );
|
| - p = *cursor;
|
| + curp = p;
|
| + num = PS_Conv_Strtol( &p, limit, 10 );
|
| +
|
| + if ( p == curp )
|
| + return 0;
|
|
|
| if ( p < limit && *p == '#' )
|
| {
|
| - *cursor = p + 1;
|
| + p++;
|
| +
|
| + curp = p;
|
| + num = PS_Conv_Strtol( &p, limit, num );
|
|
|
| - return PS_Conv_Strtol( cursor, limit, num );
|
| + if ( p == curp )
|
| + return 0;
|
| }
|
| - else
|
| - return num;
|
| +
|
| + *cursor = p;
|
| +
|
| + return num;
|
| }
|
|
|
|
|
| FT_LOCAL_DEF( FT_Fixed )
|
| PS_Conv_ToFixed( FT_Byte** cursor,
|
| FT_Byte* limit,
|
| - FT_Int power_ten )
|
| + FT_Long power_ten )
|
| {
|
| FT_Byte* p = *cursor;
|
| - FT_Fixed integral;
|
| - FT_Long decimal = 0, divider = 1;
|
| - FT_Bool sign = 0;
|
| + FT_Byte* curp;
|
| +
|
| + FT_Fixed integral = 0;
|
| + FT_Long decimal = 0;
|
| + FT_Long divider = 1;
|
| +
|
| + FT_Bool sign = 0;
|
| + FT_Bool have_overflow = 0;
|
| + FT_Bool have_underflow = 0;
|
|
|
|
|
| if ( p >= limit )
|
| - return 0;
|
| + goto Bad;
|
|
|
| if ( *p == '-' || *p == '+' )
|
| {
|
| @@ -159,13 +214,23 @@
|
|
|
| p++;
|
| if ( p == limit )
|
| - return 0;
|
| + goto Bad;
|
| }
|
|
|
| + /* read the integer part */
|
| if ( *p != '.' )
|
| - integral = PS_Conv_ToInt( &p, limit ) << 16;
|
| - else
|
| - integral = 0;
|
| + {
|
| + curp = p;
|
| + integral = PS_Conv_ToInt( &p, limit );
|
| +
|
| + if ( p == curp )
|
| + return 0;
|
| +
|
| + if ( integral > 0x7FFF )
|
| + have_overflow = 1;
|
| + else
|
| + integral = (FT_Fixed)( (FT_UInt32)integral << 16 );
|
| + }
|
|
|
| /* read the decimal part */
|
| if ( p < limit && *p == '.' )
|
| @@ -185,18 +250,14 @@
|
| if ( c < 0 || c >= 10 )
|
| break;
|
|
|
| - if ( !integral && power_ten > 0 )
|
| + if ( decimal < 0xCCCCCCCL )
|
| {
|
| - power_ten--;
|
| decimal = decimal * 10 + c;
|
| - }
|
| - else
|
| - {
|
| - if ( divider < 10000000L )
|
| - {
|
| - decimal = decimal * 10 + c;
|
| +
|
| + if ( !integral && power_ten > 0 )
|
| + power_ten--;
|
| + else
|
| divider *= 10;
|
| - }
|
| }
|
| }
|
| }
|
| @@ -204,33 +265,94 @@
|
| /* read exponent, if any */
|
| if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
|
| {
|
| + FT_Long exponent;
|
| +
|
| +
|
| p++;
|
| - power_ten += PS_Conv_ToInt( &p, limit );
|
| +
|
| + curp = p;
|
| + exponent = PS_Conv_ToInt( &p, limit );
|
| +
|
| + if ( curp == p )
|
| + return 0;
|
| +
|
| + /* arbitrarily limit exponent */
|
| + if ( exponent > 1000 )
|
| + have_overflow = 1;
|
| + else if ( exponent < -1000 )
|
| + have_underflow = 1;
|
| + else
|
| + power_ten += exponent;
|
| }
|
|
|
| + *cursor = p;
|
| +
|
| + if ( !integral && !decimal )
|
| + return 0;
|
| +
|
| + if ( have_overflow )
|
| + goto Overflow;
|
| + if ( have_underflow )
|
| + goto Underflow;
|
| +
|
| while ( power_ten > 0 )
|
| {
|
| + if ( integral >= 0xCCCCCCCL )
|
| + goto Overflow;
|
| integral *= 10;
|
| - decimal *= 10;
|
| +
|
| + if ( decimal >= 0xCCCCCCCL )
|
| + {
|
| + if ( divider == 1 )
|
| + goto Overflow;
|
| + divider /= 10;
|
| + }
|
| + else
|
| + decimal *= 10;
|
| +
|
| power_ten--;
|
| }
|
|
|
| while ( power_ten < 0 )
|
| {
|
| integral /= 10;
|
| - divider *= 10;
|
| + if ( divider < 0xCCCCCCCL )
|
| + divider *= 10;
|
| + else
|
| + decimal /= 10;
|
| +
|
| + if ( !integral && !decimal )
|
| + goto Underflow;
|
| +
|
| power_ten++;
|
| }
|
|
|
| if ( decimal )
|
| - integral += FT_DivFix( decimal, divider );
|
| + {
|
| + decimal = FT_DivFix( decimal, divider );
|
| + /* it's not necessary to check this addition for overflow */
|
| + /* due to the structure of the real number representation */
|
| + integral += decimal;
|
| + }
|
|
|
| + Exit:
|
| if ( sign )
|
| integral = -integral;
|
|
|
| - *cursor = p;
|
| -
|
| return integral;
|
| +
|
| + Bad:
|
| + FT_TRACE4(( "!!!END OF DATA:!!!" ));
|
| + return 0;
|
| +
|
| + Overflow:
|
| + integral = 0x7FFFFFFFL;
|
| + FT_TRACE4(( "!!!OVERFLOW:!!!" ));
|
| + goto Exit;
|
| +
|
| + Underflow:
|
| + FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
|
| + return 0;
|
| }
|
|
|
|
|
|
|