This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] Fix strtold on 32-bit sparc (and probably others) (BZ #16965)
- From: Aurelien Jarno <aurelien at aurel32 dot net>
- To: libc-alpha at sourceware dot org
- Cc: "Joseph S. Myers" <joseph at codesourcery dot com>, David Miller <davem at davemloft dot net>, Aurelien Jarno <aurelien at aurel32 dot net>
- Date: Tue, 20 May 2014 15:40:38 +0200
- Subject: [PATCH] Fix strtold on 32-bit sparc (and probably others) (BZ #16965)
- Authentication-results: sourceware.org; auth=none
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 | 6 ++++++
stdlib/strtod_l.c | 11 ++++++++---
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index fc75ff2..5755561 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-05-20 Aurelien Jarno <aurelien@aurel32.net>
+
+ [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 Will Newton <will.newton@linaro.org>
* sysdeps/unix/sysv/linux/aarch64/nptl/sysdep-cancel.h (PSEUDO):
diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
index 6707e48..3c449c7 100644
--- a/stdlib/strtod_l.c
+++ b/stdlib/strtod_l.c
@@ -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);
}
--
2.0.0.rc0