[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'.
This commit is contained in:
Werner Lemberg 2012-10-19 09:06:53 +02:00
parent 0708b23e80
commit 4404ec4ef5
2 changed files with 79 additions and 23 deletions

View File

@ -1,3 +1,14 @@
2012-10-19 Werner Lemberg <wl@gnu.org>
[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 <wl@gnu.org> 2012-10-17 Werner Lemberg <wl@gnu.org>
[psaux] Fix some value overflows. [psaux] Fix some value overflows.

View File

@ -105,6 +105,7 @@
Bad: Bad:
val = 0; val = 0;
FT_TRACE4(( "!!!END OF DATA:!!!" ));
goto Exit; goto Exit;
} }
@ -165,7 +166,7 @@
/* Make sure we don't read past the end. */ /* Make sure we don't read past the end. */
if ( p >= limit ) if ( p >= limit )
goto Exit; goto Bad;
} }
/* Get the nibble. */ /* Get the nibble. */
@ -202,7 +203,7 @@
/* Make sure we don't read past the end. */ /* Make sure we don't read past the end. */
if ( p >= limit ) if ( p >= limit )
goto Exit; goto Bad;
} }
/* Get the nibble. */ /* Get the nibble. */
@ -241,7 +242,7 @@
/* Make sure we don't read past the end. */ /* Make sure we don't read past the end. */
if ( p >= limit ) if ( p >= limit )
goto Exit; goto Bad;
} }
/* Get the nibble. */ /* Get the nibble. */
@ -254,13 +255,21 @@
/* Arbitrarily limit exponent. */ /* Arbitrarily limit exponent. */
if ( exponent > 1000 ) if ( exponent > 1000 )
goto Exit; {
if ( exponent_sign )
goto Underflow;
else
goto Overflow;
}
} }
if ( exponent_sign ) if ( exponent_sign )
exponent = -exponent; exponent = -exponent;
} }
if ( !number )
goto Exit;
/* We don't check `power_ten' and `exponent_add'. */ /* We don't check `power_ten' and `exponent_add'. */
exponent += power_ten + exponent_add; exponent += power_ten + exponent_add;
@ -329,7 +338,7 @@
/* Check for overflow and underflow. */ /* Check for overflow and underflow. */
if ( FT_ABS( integer_length ) > 5 ) if ( FT_ABS( integer_length ) > 5 )
goto Exit; goto Overflow;
/* Remove non-significant digits. */ /* Remove non-significant digits. */
if ( integer_length < 0 ) if ( integer_length < 0 )
@ -358,17 +367,32 @@
number *= power_tens[-fraction_length]; number *= power_tens[-fraction_length];
if ( number > 0x7FFFL ) if ( number > 0x7FFFL )
goto Exit; goto Overflow;
result = number << 16; result = number << 16;
} }
} }
Exit:
if ( sign ) if ( sign )
result = -result; result = -result;
Exit:
return result; 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;
} }
@ -381,12 +405,46 @@
} }
/* read a floating point number, either integer or real */
static FT_Fixed
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] );
if ( scaling )
val *= power_tens[scaling];
if ( val > 0x7FFF )
{
val = 0x7FFFFFFFL;
goto Overflow;
}
else if ( val < -0x7FFF )
{
val = -0x7FFFFFFFL;
goto Overflow;
}
return val << 16;
Overflow:
FT_TRACE4(( "!!!OVERFLOW:!!!" ));
return val;
}
}
/* read a floating point number, either integer or real */ /* read a floating point number, either integer or real */
static FT_Fixed static FT_Fixed
cff_parse_fixed( FT_Byte** d ) cff_parse_fixed( FT_Byte** d )
{ {
return **d == 30 ? cff_parse_real( d[0], d[1], 0, NULL ) return do_fixed( d, 0 );
: cff_parse_integer( d[0], d[1] ) << 16;
} }
@ -396,20 +454,7 @@
cff_parse_fixed_scaled( FT_Byte** d, cff_parse_fixed_scaled( FT_Byte** d,
FT_Long scaling ) FT_Long scaling )
{ {
if ( **d == 30 ) return do_fixed( d, scaling );
return cff_parse_real( d[0], d[1], scaling, NULL );
else
{
FT_Long val = cff_parse_integer( d[0], d[1] ) * power_tens[scaling];
if ( val > 0x7FFF )
return 0x7FFFFFFFL;
else if ( val < -0x7FFF )
return -0x7FFFFFFFL;
return val << 16;
}
} }