]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix strtold on 32-bit sparc (and probably others) (BZ #16965)
authorAurelien Jarno <aurelien@aurel32.net>
Tue, 20 May 2014 12:41:44 +0000 (14:41 +0200)
committerAurelien Jarno <aurelien@aurel32.net>
Tue, 20 May 2014 16:44:28 +0000 (18:44 +0200)
This patch fixes an issue observed running the tst-strtod-round test on
32 bit sparc. In some conditions, strtold calls round_and_return, which in
turn calls __mpn_rshift with cnt = 0, while stdlib/rshift.c explicitly says
that cnts should satisfy 0 < CNT < BITS_PER_MP_LIMB. In this case, the code
end up doing a logical shift right of the same amount than the register,
which is undefined in the C standard.

Due to this bug, 32-bit sparc does not correctly convert the value
"0x1p-16446", but it is likely that other architectures are also
affected for other input values.

ChangeLog
NEWS
stdlib/strtod_l.c

index 59464a6478a650f074521f1275b6f9d6a0e476d7..e87fc225fb153878d08ef704fee70bc4ed46df71 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
        * localedata/tst-langinfo.sh: Send output to stdout.
        * localedata/tst-langinfo-static.c: New file.
 
+       [BZ #16965]
+       * stdlib/strtod_l.c (round_and_return): Add code to shift limbs
+       when the shift amount is modulo the limb size.
+
 2014-05-20  Richard Henderson  <rth@redhat.com>
 
        [BZ #16967]
diff --git a/NEWS b/NEWS
index d9ce8f9af8acbe72cba9900c9740359f2a56d6cd..8aaf2f4cb5b15f107b2ff284c8c78b6ce7e8ba14 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -18,7 +18,7 @@ Version 2.20
   16760, 16770, 16786, 16789, 16791, 16799, 16800, 16815, 16823, 16824,
   16831, 16838, 16849, 16854, 16876, 16877, 16885, 16888, 16890, 16912,
   16915, 16916, 16917, 16922, 16927, 16928, 16932, 16943, 16958, 16966,
-  16967.
+  16967, 16965.
 
 * The minimum Linux kernel version that this version of the GNU C Library
   can be used with is 2.6.32.
index 6707e482a443008af8294cc23d797333aad4894e..3c449c7d54d97d647b73758743f62afda75e0cc4 100644 (file)
@@ -243,9 +243,14 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
          more_bits |= ((round_limb & ((((mp_limb_t) 1) << round_bit) - 1))
                        != 0);
 
-         (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB],
-                              RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
-                              shift % BITS_PER_MP_LIMB);
+         /* __mpn_rshift requires 0 < shift < BITS_PER_MP_LIMB.  */
+         if ((shift % BITS_PER_MP_LIMB) != 0)
+           (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB],
+                                RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
+                                shift % BITS_PER_MP_LIMB);
+         else
+           for (i = 0; i < RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB); i++)
+             retval[i] = retval[i + (shift / BITS_PER_MP_LIMB)];
          MPN_ZERO (&retval[RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)],
                    shift / BITS_PER_MP_LIMB);
        }