From b038f394a9fb41b3bc45a55e6bffac5bac9fe9ef Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 2 Jun 2022 18:28:57 +0930 Subject: [PATCH] ubsan: signed integer overflow in atof_generic Fix the signed overflows by using unsigned variables and detect overflow at BUG! comment. * atof-generic.c (atof_generic): Avoid signed integer overflow. Return ERROR_EXPONENT_OVERFLOW if exponent overflows a long. --- gas/atof-generic.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gas/atof-generic.c b/gas/atof-generic.c index c3f818d9489..91583194868 100644 --- a/gas/atof-generic.c +++ b/gas/atof-generic.c @@ -72,11 +72,11 @@ atof_generic (/* return pointer to just AFTER number we read. */ const char *string_of_decimal_exponent_marks, FLONUM_TYPE *address_of_generic_floating_point_number) { - int return_value; /* 0 means OK. */ + int return_value = 0; /* 0 means OK. */ char *first_digit; unsigned int number_of_digits_before_decimal; unsigned int number_of_digits_after_decimal; - long decimal_exponent; + unsigned long decimal_exponent; unsigned int number_of_digits_available; char digits_sign_char; @@ -204,7 +204,7 @@ atof_generic (/* return pointer to just AFTER number we read. */ deleting zeros after decimal. In this case the decimal mark and the first zero digits after decimal mark are skipped. */ seen_significant_digit = 0; - signed long subtract_decimal_exponent = 0; + unsigned long subtract_decimal_exponent = 0; if (c && IS_DECIMAL_MARK (c)) { @@ -300,10 +300,11 @@ atof_generic (/* return pointer to just AFTER number we read. */ { if (ISDIGIT (c)) { + if (decimal_exponent > LONG_MAX / 10 + || (decimal_exponent == LONG_MAX / 10 + && c > '0' + (char) (LONG_MAX - LONG_MAX / 10 * 10))) + return_value = ERROR_EXPONENT_OVERFLOW; decimal_exponent = decimal_exponent * 10 + c - '0'; - /* - * BUG! If we overflow here, we lose! - */ } else { @@ -327,7 +328,6 @@ atof_generic (/* return pointer to just AFTER number we read. */ number_of_digits_available = number_of_digits_before_decimal + number_of_digits_after_decimal; - return_value = 0; if (number_of_digits_available == 0) { address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */ @@ -505,7 +505,7 @@ atof_generic (/* return pointer to just AFTER number we read. */ size_of_power_in_littlenums = precision; /* Precision has a built-in fudge factor so we get a few guard bits. */ - decimal_exponent_is_negative = decimal_exponent < 0; + decimal_exponent_is_negative = (long) decimal_exponent < 0; if (decimal_exponent_is_negative) { decimal_exponent = -decimal_exponent; -- 2.30.2