When 'exp' is of type 'int', the line exp = -exp; crashes when the program was compiled with "gcc -ftrapv" and exp == INT_MIN.
2023-08-19 Bruno Haible <[email protected]> ldexpl: Fix signed integer overflow. * lib/ldexpl.c (ldexpl): Use an 'unsigned int' variable to represent the absolute value of exp without overflow. diff --git a/lib/ldexpl.c b/lib/ldexpl.c index 47f133c58f..255917eb30 100644 --- a/lib/ldexpl.c +++ b/lib/ldexpl.c @@ -39,8 +39,9 @@ ldexpl (long double x, int exp) long double ldexpl (long double x, int exp) { + unsigned int uexp; long double factor; - int bit; + unsigned int bit; DECL_LONG_DOUBLE_ROUNDING BEGIN_LONG_DOUBLE_ROUNDING (); @@ -50,21 +51,25 @@ ldexpl (long double x, int exp) { if (exp < 0) { - exp = -exp; + /* Avoid signed integer overflow when exp == INT_MIN. */ + uexp = (unsigned int) (-1 - exp) + 1; factor = 0.5L; } else - factor = 2.0L; + { + uexp = exp; + factor = 2.0L; + } - if (exp > 0) + if (uexp > 0) for (bit = 1;;) { /* Invariant: Here bit = 2^i, factor = 2^-2^i or = 2^2^i, - and bit <= exp. */ - if (exp & bit) + and bit <= uexp. */ + if (uexp & bit) x *= factor; bit <<= 1; - if (bit > exp) + if (bit > uexp) break; factor = factor * factor; }
