aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2018-11-26 14:17:40 -0800
committerH. Peter Anvin <hpa@zytor.com>2018-11-26 14:17:40 -0800
commit79a070eea944c499f50afc02ff421dae37ed7c65 (patch)
treea48779a550635c15c0568d6831254bea58f71a52
parentda794322557cb361457d5384806bace5662daeaa (diff)
downloadnasm-79a070eea944c499f50afc02ff421dae37ed7c65.tar.gz
nasm-79a070eea944c499f50afc02ff421dae37ed7c65.tar.xz
nasm-79a070eea944c499f50afc02ff421dae37ed7c65.zip
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.c9
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)