diff --git a/ChangeLog b/ChangeLog index d9fb1a69b..682b7c7e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2012-10-19 Werner Lemberg + + [cff] Fix more value errors and improve tracing. + + * src/cff/cffparse.c (cff_parse_integer): Emit tracing message in + case of error. + (cff_parse_real): Handle and trace overflow, underflow, and bad data + consistently. + (do_fixed): New helper function, handling and tracing overflow. + (cff_parse_fixed, cff_parse_fixed_scaled): Use `do_fixed'. + 2012-10-17 Werner Lemberg [psaux] Fix some value overflows. diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c index 2e93bd3a1..015a1d190 100644 --- a/src/cff/cffparse.c +++ b/src/cff/cffparse.c @@ -105,6 +105,7 @@ Bad: val = 0; + FT_TRACE4(( "!!!END OF DATA:!!!" )); goto Exit; } @@ -165,7 +166,7 @@ /* Make sure we don't read past the end. */ if ( p >= limit ) - goto Exit; + goto Bad; } /* Get the nibble. */ @@ -202,7 +203,7 @@ /* Make sure we don't read past the end. */ if ( p >= limit ) - goto Exit; + goto Bad; } /* Get the nibble. */ @@ -241,7 +242,7 @@ /* Make sure we don't read past the end. */ if ( p >= limit ) - goto Exit; + goto Bad; } /* Get the nibble. */ @@ -254,13 +255,21 @@ /* Arbitrarily limit exponent. */ if ( exponent > 1000 ) - goto Exit; + { + if ( exponent_sign ) + goto Underflow; + else + goto Overflow; + } } if ( exponent_sign ) exponent = -exponent; } + if ( !number ) + goto Exit; + /* We don't check `power_ten' and `exponent_add'. */ exponent += power_ten + exponent_add; @@ -329,7 +338,7 @@ /* Check for overflow and underflow. */ if ( FT_ABS( integer_length ) > 5 ) - goto Exit; + goto Overflow; /* Remove non-significant digits. */ if ( integer_length < 0 ) @@ -358,17 +367,32 @@ number *= power_tens[-fraction_length]; if ( number > 0x7FFFL ) - goto Exit; + goto Overflow; result = number << 16; } } + Exit: if ( sign ) result = -result; - Exit: return result; + + Overflow: + result = 0x7FFFFFFFL; + FT_TRACE4(( "!!!OVERFLOW:!!!" )); + goto Exit; + + Underflow: + result = 0; + FT_TRACE4(( "!!!UNDERFLOW:!!!" )); + goto Exit; + + Bad: + result = 0; + FT_TRACE4(( "!!!END OF DATA:!!!" )); + goto Exit; } @@ -383,36 +407,57 @@ /* read a floating point number, either integer or real */ static FT_Fixed - cff_parse_fixed( FT_Byte** d ) - { - return **d == 30 ? cff_parse_real( d[0], d[1], 0, NULL ) - : cff_parse_integer( d[0], d[1] ) << 16; - } - - - /* read a floating point number, either integer or real, */ - /* but return `10^scaling' times the number read in */ - static FT_Fixed - cff_parse_fixed_scaled( FT_Byte** d, - FT_Long scaling ) + do_fixed( FT_Byte** d, + FT_Long scaling ) { if ( **d == 30 ) return cff_parse_real( d[0], d[1], scaling, NULL ); else { - FT_Long val = cff_parse_integer( d[0], d[1] ) * power_tens[scaling]; + FT_Long val = cff_parse_integer( d[0], d[1] ); + + if ( scaling ) + val *= power_tens[scaling]; if ( val > 0x7FFF ) - return 0x7FFFFFFFL; + { + val = 0x7FFFFFFFL; + goto Overflow; + } else if ( val < -0x7FFF ) - return -0x7FFFFFFFL; + { + val = -0x7FFFFFFFL; + goto Overflow; + } return val << 16; + + Overflow: + FT_TRACE4(( "!!!OVERFLOW:!!!" )); + return val; } } + /* read a floating point number, either integer or real */ + static FT_Fixed + cff_parse_fixed( FT_Byte** d ) + { + return do_fixed( d, 0 ); + } + + + /* read a floating point number, either integer or real, */ + /* but return `10^scaling' times the number read in */ + static FT_Fixed + cff_parse_fixed_scaled( FT_Byte** d, + FT_Long scaling ) + { + return do_fixed( d, scaling ); + } + + /* read a floating point number, either integer or real, */ /* and return it as precise as possible -- `scaling' returns */ /* the scaling factor (as a power of 10) */