]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix scalbn, scalbln integer overflow.
authorJoseph Myers <joseph@codesourcery.com>
Fri, 2 Mar 2012 15:32:56 +0000 (15:32 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Fri, 2 Mar 2012 15:32:56 +0000 (15:32 +0000)
15 files changed:
ChangeLog
NEWS
math/libm-test.inc
sysdeps/ieee754/dbl-64/s_scalbln.c
sysdeps/ieee754/dbl-64/s_scalbn.c
sysdeps/ieee754/dbl-64/wordsize-64/s_scalbln.c
sysdeps/ieee754/dbl-64/wordsize-64/s_scalbn.c
sysdeps/ieee754/flt-32/s_scalblnf.c
sysdeps/ieee754/flt-32/s_scalbnf.c
sysdeps/ieee754/ldbl-128/s_scalblnl.c
sysdeps/ieee754/ldbl-128/s_scalbnl.c
sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c
sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c
sysdeps/ieee754/ldbl-96/s_scalblnl.c
sysdeps/ieee754/ldbl-96/s_scalbnl.c

index cb3e30b5343a2a1310f25370a0effd9927217b50..b856c4ba5a65a238a39e1483e402bed7a350e820 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 2012-03-02  Joseph Myers  <joseph@codesourcery.com>
 
+       [BZ #10135]
+       * sysdeps/ieee754/dbl-64/s_scalbln.c (__scalbln): First test for
+       small n, then large n, before computing and testing k+n.
+       * sysdeps/ieee754/dbl-64/s_scalbn.c (__scalbn): Likewise.
+       * sysdeps/ieee754/dbl-64/wordsize-64/s_scalbln.c (__scalbln):
+       Likewise.
+       * sysdeps/ieee754/dbl-64/wordsize-64/s_scalbn.c (__scalbn):
+       Likewise.
+       * sysdeps/ieee754/flt-32/s_scalblnf.c (__scalblnf): Likewise.
+       * sysdeps/ieee754/flt-32/s_scalbnf.c (__scalbnf): Likewise.
+       * sysdeps/ieee754/ldbl-128/s_scalblnl.c (__scalblnl): Likewise.
+       * sysdeps/ieee754/ldbl-128/s_scalbnl.c (__scalbnl): Likewise.
+       * sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c (__scalblnl): Likewise.
+       * sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c (__scalbnl): Likewise.
+       * sysdeps/ieee754/ldbl-96/s_scalblnl.c (__scalblnl): Likewise.
+       * sysdeps/ieee754/ldbl-96/s_scalbnl.c (__scalbnl): Likewise.
+       * math/libm-test.inc (scalbn_test): Add more tests.
+       (scalbln_test): Likewise.
+
        * manual/filesys.texi (mode_t): Describe constraints on size and
        signedness, not exact equivalence to a particular type.
        (ino_t): Likewise.
diff --git a/NEWS b/NEWS
index 6c0bc4acab8018b394d37c0b0fa67d644875f32f..5d7d0935986d465d3e72d5019ce0c6b880729836 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,10 +10,10 @@ Version 2.16
 * The following bugs are resolved with this release:
 
   174, 350, 411, 2541, 2547, 2548, 3335, 3992, 4026, 4108, 4596, 4822, 5077,
-  5461, 5805, 5993, 6884, 6907, 9739, 9902, 10110, 10140, 10210, 11174,
-  11322, 11365, 11494, 12047, 13058, 13525, 13526, 13527, 13528, 13529,
-  13530, 13531, 13532, 13533, 13547, 13551, 13552, 13553, 13555, 13559,
-  13583, 13618, 13637, 13695, 13704, 13706, 13738, 13786
+  5461, 5805, 5993, 6884, 6907, 9739, 9902, 10110, 10135, 10140, 10210,
+  11174, 11322, 11365, 11494, 12047, 13058, 13525, 13526, 13527, 13528,
+  13529, 13530, 13531, 13532, 13533, 13547, 13551, 13552, 13553, 13555,
+  13559, 13583, 13618, 13637, 13695, 13704, 13706, 13738, 13786
 
 * ISO C11 support:
 
index 5bc0d408724d7ce8304e7b1c1bbb717902fa4022..ef7a253662976379f80a376c1c78fa5a05b15d09 100644 (file)
@@ -5790,6 +5790,15 @@ scalbn_test (void)
 
   TEST_fi_f (scalbn, 1, 0L, 1);
 
+  TEST_fi_f (scalbn, 1, INT_MAX, plus_infty);
+  TEST_fi_f (scalbn, 1, INT_MIN, plus_zero);
+  TEST_fi_f (scalbn, max_value, INT_MAX, plus_infty);
+  TEST_fi_f (scalbn, max_value, INT_MIN, plus_zero);
+  TEST_fi_f (scalbn, min_value, INT_MAX, plus_infty);
+  TEST_fi_f (scalbn, min_value, INT_MIN, plus_zero);
+  TEST_fi_f (scalbn, min_value / 4, INT_MAX, plus_infty);
+  TEST_fi_f (scalbn, min_value / 4, INT_MIN, plus_zero);
+
   END (scalbn);
 }
 
@@ -5812,6 +5821,35 @@ scalbln_test (void)
 
   TEST_fl_f (scalbln, 1, 0L, 1);
 
+  TEST_fi_f (scalbln, 1, INT_MAX, plus_infty);
+  TEST_fi_f (scalbln, 1, INT_MIN, plus_zero);
+  TEST_fi_f (scalbln, max_value, INT_MAX, plus_infty);
+  TEST_fi_f (scalbln, max_value, INT_MIN, plus_zero);
+  TEST_fi_f (scalbln, min_value, INT_MAX, plus_infty);
+  TEST_fi_f (scalbln, min_value, INT_MIN, plus_zero);
+  TEST_fi_f (scalbln, min_value / 4, INT_MAX, plus_infty);
+  TEST_fi_f (scalbln, min_value / 4, INT_MIN, plus_zero);
+
+  TEST_fi_f (scalbln, 1, LONG_MAX, plus_infty);
+  TEST_fi_f (scalbln, 1, LONG_MIN, plus_zero);
+  TEST_fi_f (scalbln, max_value, LONG_MAX, plus_infty);
+  TEST_fi_f (scalbln, max_value, LONG_MIN, plus_zero);
+  TEST_fi_f (scalbln, min_value, LONG_MAX, plus_infty);
+  TEST_fi_f (scalbln, min_value, LONG_MIN, plus_zero);
+  TEST_fi_f (scalbln, min_value / 4, LONG_MAX, plus_infty);
+  TEST_fi_f (scalbln, min_value / 4, LONG_MIN, plus_zero);
+
+#if LONG_MAX >= 0x100000000
+  TEST_fi_f (scalbln, 1, 0x88000000L, plus_infty);
+  TEST_fi_f (scalbln, 1, -0x88000000L, plus_zero);
+  TEST_fi_f (scalbln, max_value, 0x88000000L, plus_infty);
+  TEST_fi_f (scalbln, max_value, -0x88000000L, plus_zero);
+  TEST_fi_f (scalbln, min_value, 0x88000000L, plus_infty);
+  TEST_fi_f (scalbln, min_value, -0x88000000L, plus_zero);
+  TEST_fi_f (scalbln, min_value / 4, 0x88000000L, plus_infty);
+  TEST_fi_f (scalbln, min_value / 4, -0x88000000L, plus_zero);
+#endif
+
   END (scalbn);
 }
 
index 89174b47fbb88a37dc1a6856e15ded29d8315c8c..b5903c97d03f7915296b08a2916d843af1e81710 100644 (file)
@@ -38,11 +38,13 @@ __scalbln (double x, long int n)
            k = ((hx&0x7ff00000)>>20) - 54;
            }
        if (__builtin_expect(k==0x7ff, 0)) return x+x;  /* NaN or Inf */
-       k = k+n;
-       if (__builtin_expect(n> 50000 || k >  0x7fe, 0))
-         return huge*__copysign(huge,x); /* overflow  */
        if (__builtin_expect(n< -50000, 0))
          return tiny*__copysign(tiny,x); /*underflow*/
+       if (__builtin_expect(n> 50000 || k+n > 0x7fe, 0))
+         return huge*__copysign(huge,x); /* overflow  */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+       k = k+n;
        if (__builtin_expect(k > 0, 1))         /* normal result */
            {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
        if (k <= -54)
index 1e67dbe5ebd4a812d38551906aa420545a5e956c..c2488fbbee3710b269c5059570bdf1dd8c0b3d65 100644 (file)
@@ -38,11 +38,13 @@ __scalbn (double x, int n)
            k = ((hx&0x7ff00000)>>20) - 54;
            }
        if (__builtin_expect(k==0x7ff, 0)) return x+x;  /* NaN or Inf */
-       k = k+n;
-       if (__builtin_expect(n> 50000 || k >  0x7fe, 0))
-         return huge*__copysign(huge,x); /* overflow  */
        if (__builtin_expect(n< -50000, 0))
          return tiny*__copysign(tiny,x); /*underflow*/
+       if (__builtin_expect(n> 50000 || k+n > 0x7fe, 0))
+         return huge*__copysign(huge,x); /* overflow  */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+       k = k+n;
        if (__builtin_expect(k > 0, 1))         /* normal result */
            {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
        if (k <= -54)
index d6b97b5483c0bb38a6a40200d7988e42196ac317..1d0da687c106fdf2bef1201c60ea07a806d746ad 100644 (file)
@@ -39,11 +39,13 @@ __scalbln (double x, long int n)
            k = ((ix >> 52) & 0x7ff) - 54;
            }
        if (__builtin_expect(k==0x7ff, 0)) return x+x;  /* NaN or Inf */
-       k = k+n;
-       if (__builtin_expect(n> 50000 || k >  0x7fe, 0))
-         return huge*__copysign(huge,x); /* overflow  */
        if (__builtin_expect(n< -50000, 0))
          return tiny*__copysign(tiny,x); /*underflow*/
+       if (__builtin_expect(n> 50000 || k+n > 0x7fe, 0))
+         return huge*__copysign(huge,x); /* overflow  */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+       k = k+n;
        if (__builtin_expect(k > 0, 1))         /* normal result */
            {INSERT_WORDS64(x,(ix&UINT64_C(0x800fffffffffffff))|(k<<52));
              return x;}
index 7f0e21f646fa177f902b965e48e19de1be9d3fd8..e183c3875f6d4bbde9a5fd73a10a23d4393e74b7 100644 (file)
@@ -39,11 +39,13 @@ __scalbn (double x, int n)
            k = ((ix >> 52) & 0x7ff) - 54;
            }
        if (__builtin_expect(k==0x7ff, 0)) return x+x;  /* NaN or Inf */
-       k = k+n;
-       if (__builtin_expect(n> 50000 || k >  0x7fe, 0))
-         return huge*__copysign(huge,x); /* overflow  */
        if (__builtin_expect(n< -50000, 0))
          return tiny*__copysign(tiny,x); /*underflow*/
+       if (__builtin_expect(n> 50000 || k+n > 0x7fe, 0))
+         return huge*__copysign(huge,x); /* overflow  */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+       k = k+n;
        if (__builtin_expect(k > 0, 1))         /* normal result */
            {INSERT_WORDS64(x,(ix&UINT64_C(0x800fffffffffffff))|(k<<52));
              return x;}
index 5256c3259228f77ba5e4fb6f29396e28fe27b2b1..2a2d7ab651e6e218930f174eeed9dfd16969a755 100644 (file)
@@ -35,11 +35,13 @@ __scalblnf (float x, long int n)
            k = ((ix&0x7f800000)>>23) - 25;
            }
        if (__builtin_expect(k==0xff, 0)) return x+x;   /* NaN or Inf */
-       k = k+n;
-       if (__builtin_expect(n> 50000 || k >  0xfe, 0))
-         return huge*copysignf(huge,x); /* overflow  */
        if (__builtin_expect(n< -50000, 0))
          return tiny*copysignf(tiny,x);        /*underflow*/
+       if (__builtin_expect(n> 50000 || k+n > 0xfe, 0))
+         return huge*copysignf(huge,x); /* overflow  */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+       k = k+n;
        if (__builtin_expect(k > 0, 1))         /* normal result */
            {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
        if (k <= -25)
index 3be2925a03a4263dbecef18c8c461ab71fbd1a6f..a7cb1a1a49571ea1c2ece6b0a59cd5af6eb6a36d 100644 (file)
@@ -35,11 +35,13 @@ __scalbnf (float x, int n)
            k = ((ix&0x7f800000)>>23) - 25;
            }
        if (__builtin_expect(k==0xff, 0)) return x+x;   /* NaN or Inf */
-       k = k+n;
-       if (__builtin_expect(n> 50000 || k >  0xfe, 0))
-         return huge*__copysignf(huge,x); /* overflow  */
        if (__builtin_expect(n< -50000, 0))
          return tiny*__copysignf(tiny,x);      /*underflow*/
+       if (__builtin_expect(n> 50000 || k+n > 0xfe, 0))
+         return huge*__copysignf(huge,x); /* overflow  */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+       k = k+n;
        if (__builtin_expect(k > 0, 1))         /* normal result */
            {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
        if (k <= -25)
index f5624e2a7356c66f1d3bfb6b18373f2a41e6276d..9ad976bb116eb0246c4c0aa56da739952101d47a 100644 (file)
@@ -46,10 +46,12 @@ long double __scalblnl (long double x, long int n)
            k = ((hx>>48)&0x7fff) - 114;
        }
         if (k==0x7fff) return x+x;             /* NaN or Inf */
-        k = k+n;
-        if (n> 50000 || k > 0x7ffe)
-         return huge*__copysignl(huge,x); /* overflow  */
        if (n< -50000) return tiny*__copysignl(tiny,x); /*underflow*/
+        if (n> 50000 || k+n > 0x7ffe)
+         return huge*__copysignl(huge,x); /* overflow  */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+        k = k+n;
         if (k > 0)                             /* normal result */
            {SET_LDOUBLE_MSW64(x,(hx&0x8000ffffffffffffULL)|(k<<48)); return x;}
         if (k <= -114)
index b9de0f74fc46d68b0979169e5c14f30a8751d9fd..a928ecccec7f2340ace62ce726bb5e937caa005b 100644 (file)
@@ -46,10 +46,12 @@ long double __scalbnl (long double x, int n)
            k = ((hx>>48)&0x7fff) - 114;
        }
         if (k==0x7fff) return x+x;             /* NaN or Inf */
-        k = k+n;
-        if (n> 50000 || k > 0x7ffe)
-         return huge*__copysignl(huge,x); /* overflow  */
        if (n< -50000) return tiny*__copysignl(tiny,x); /*underflow*/
+        if (n> 50000 || k+n > 0x7ffe)
+         return huge*__copysignl(huge,x); /* overflow  */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+        k = k+n;
         if (k > 0)                             /* normal result */
            {SET_LDOUBLE_MSW64(x,(hx&0x8000ffffffffffffULL)|(k<<48)); return x;}
         if (k <= -114)
index a1632e77fc59c06a7a9ab578f79cf1c1f835a833..2c30d1c78a4297add02657ee710391365636989f 100644 (file)
@@ -52,10 +52,12 @@ long double __scalblnl (long double x, long int n)
            k = ((hx>>52)&0x7ff) - 54;
        }
        else if (k==0x7ff) return x+x;          /* NaN or Inf */
-       k = k+n;
-       if (n> 50000 || k > 0x7fe)
-         return huge*__copysignl(huge,x); /* overflow */
        if (n< -50000) return tiny*__copysignl(tiny,x); /*underflow */
+       if (n> 50000 || k+n > 0x7fe)
+         return huge*__copysignl(huge,x); /* overflow */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+       k = k+n;
        if (k > 0) {                            /* normal result */
            hx = (hx&0x800fffffffffffffULL)|(k<<52);
            if ((lx & 0x7fffffffffffffffULL) == 0) { /* low part +-0 */
index a52cd42f0b1e44a45ce969d6846f7a834d23fbff..48102efcf51bf0c9a8ead08eda422046c0d93d0d 100644 (file)
@@ -52,10 +52,12 @@ long double __scalbnl (long double x, int n)
            k = ((hx>>52)&0x7ff) - 54;
        }
        else if (k==0x7ff) return x+x;          /* NaN or Inf */
-       k = k+n;
-       if (n> 50000 || k > 0x7fe)
-         return huge*__copysignl(huge,x); /* overflow */
        if (n< -50000) return tiny*__copysignl(tiny,x); /*underflow */
+       if (n> 50000 || k+n > 0x7fe)
+         return huge*__copysignl(huge,x); /* overflow */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+       k = k+n;
        if (k > 0) {                            /* normal result */
            hx = (hx&0x800fffffffffffffULL)|(k<<52);
            if ((lx & 0x7fffffffffffffffULL) == 0) { /* low part +-0 */
index ada587b9d5d41959839b282afc83fbff67457bc1..755a212555ed55a7a6df03b2b697606ab0816e06 100644 (file)
@@ -43,11 +43,13 @@ __scalblnl (long double x, long int n)
            k = (hx&0x7fff) - 63;
            }
        if (__builtin_expect(k==0x7fff, 0)) return x+x; /* NaN or Inf */
-       k = k+n;
-       if (__builtin_expect(n> 50000 || k > 0x7ffe, 0))
-         return huge*__copysignl(huge,x); /* overflow  */
        if (__builtin_expect(n< -50000, 0))
          return tiny*__copysignl(tiny,x);
+       if (__builtin_expect(n> 50000 || k+n > 0x7ffe, 0))
+         return huge*__copysignl(huge,x); /* overflow  */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+       k = k+n;
        if (__builtin_expect(k > 0, 1))         /* normal result */
            {SET_LDOUBLE_EXP(x,(es&0x8000)|k); return x;}
        if (k <= -63)
index 6a41920aca6197d3b1b82922e1edb4a9d07f80e5..6946cf232f1d39eb4e591a6636f2a815dba98d13 100644 (file)
@@ -43,11 +43,13 @@ __scalbnl (long double x, int n)
            k = (hx&0x7fff) - 64;
            }
        if (__builtin_expect(k==0x7fff, 0)) return x+x; /* NaN or Inf */
-       k = k+n;
-       if (__builtin_expect(n> 50000 || k > 0x7ffe, 0))
-         return huge*__copysignl(huge,x); /* overflow  */
        if (__builtin_expect(n< -50000, 0))
          return tiny*__copysignl(tiny,x);
+       if (__builtin_expect(n> 50000 || k+n > 0x7ffe, 0))
+         return huge*__copysignl(huge,x); /* overflow  */
+       /* Now k and n are bounded we know that k = k+n does not
+          overflow.  */
+       k = k+n;
        if (__builtin_expect(k > 0, 1))         /* normal result */
            {SET_LDOUBLE_EXP(x,(es&0x8000)|k); return x;}
        if (k <= -64)