From 4406c41c1d6088abf01c216e49700cd3f8f01fcc Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Tue, 20 May 2014 14:41:44 +0200 Subject: Fix strtold on 32-bit sparc (and probably others) (BZ #16965) 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. --- stdlib/strtod_l.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'stdlib') diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c index 6707e482a4..3c449c7d54 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); } -- cgit 1.4.1