From: Bruno Haible Date: Sat, 19 Aug 2023 23:41:56 +0000 (+0200) Subject: ldexpl: Fix signed integer overflow. X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=3d4cd7d40faa72525386df67305942ff717666ec;p=gnulib.git 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/ChangeLog b/ChangeLog index 315e8dcc10..8ad2f8e5eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2023-08-19 Bruno Haible + + ldexpl: Fix signed integer overflow. + * lib/ldexpl.c (ldexpl): Use an 'unsigned int' variable to represent the + absolute value of exp without overflow. + 2023-08-19 Bruno Haible logbl: Work around endless loop on OpenBSD 7.3/mips64. diff --git a/lib/ldexpl.c b/lib/ldexpl.c index 47f133c58f..51aed6f6d4 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 == 0 || bit > uexp) break; factor = factor * factor; }