diff options
author | H. Peter Anvin <hpa@zytor.com> | 2018-11-26 14:17:40 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2018-11-26 14:17:40 -0800 |
commit | 79a070eea944c499f50afc02ff421dae37ed7c65 (patch) | |
tree | a48779a550635c15c0568d6831254bea58f71a52 | |
parent | da794322557cb361457d5384806bace5662daeaa (diff) | |
download | nasm-79a070eea944c499f50afc02ff421dae37ed7c65.tar.gz |
BR 3392368: correct handling of exact limb switch
When we have an exact limb switch, we may end up with a case where the
value no longer has any remaining valid bits. In that case, we end up
relying on the expression *mp |= v << ms shifting the bits on the
subsequent limb all the way to zero, but that is not how real hardware
works when the shift count equals the width of the type. This is
undefined behavior and does, in fact, produce the wrong result.
Instead, change the test for limb shift to (ms < 0), meaning that we
defer the advance to the next limb until we actually need it. At that
point, change the shift into the *old* limb to have a cast to
(fp_2limb) which means the shift right of LIMB_BITS is valid and
produces a zero value as expected.
Reported-by: Brooks Moses <bmoses@google.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | asm/float.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/asm/float.c b/asm/float.c index 7d313a59..17df6c36 100644 --- a/asm/float.c +++ b/asm/float.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- * * - * Copyright 1996-2017 The NASM Authors - All Rights Reserved + * Copyright 1996-2018 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * @@ -549,14 +549,15 @@ static bool ieee_flconvert_bin(const char *string, int bits, } if (seendigit) { - if (ms <= 0) { - *mp |= v >> -ms; + if (ms < 0) { + /* Cast to fp_2limb as ms == -LIMB_BITS is possible. */ + *mp |= (fp_2limb)v >> -ms; mp++; if (mp > &mult[MANT_LIMBS]) mp = &mult[MANT_LIMBS]; /* Guard slot */ ms += LIMB_BITS; } - *mp |= v << (ms % (sizeof(fp_limb) * CHAR_BIT)); + *mp |= v << ms; ms -= bits; if (!seendot) |