]> Savannah Git Hosting - gnulib.git/commitdiff
ldexpl: Fix signed integer overflow.
authorBruno Haible <bruno@clisp.org>
Sat, 19 Aug 2023 23:41:56 +0000 (01:41 +0200)
committerBruno Haible <bruno@clisp.org>
Wed, 30 Aug 2023 10:16:17 +0000 (12:16 +0200)
* lib/ldexpl.c (ldexpl): Use an 'unsigned int' variable to represent the
absolute value of exp without overflow.

ChangeLog
lib/ldexpl.c

index 315e8dcc10f09f3e28d993df95aae4ccef4e6b4c..8ad2f8e5eb8c3179a314f217f99f6a2d0a4aab1a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2023-08-19  Bruno Haible  <bruno@clisp.org>
+
+       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  <bruno@clisp.org>
 
        logbl: Work around endless loop on OpenBSD 7.3/mips64.
index 47f133c58ff1665f0e4eba83b9ae4aef91217867..51aed6f6d44ac508bb81cb6e12ced2e6f8880c4c 100644 (file)
@@ -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;
           }