1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

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.
This commit is contained in:
Aurelien Jarno
2014-05-20 14:41:44 +02:00
parent ae75a883f2
commit 4406c41c1d
3 changed files with 13 additions and 4 deletions

View 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);
}