summaryrefslogtreecommitdiffstats
path: root/arith.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-02-14 06:39:54 -0800
committerKaz Kylheku <kaz@kylheku.com>2022-02-14 06:39:54 -0800
commit4355d30b13d462ab334380a3dd45258811d1690e (patch)
tree113077bbd0d3c491f14027ee087f16fd800fdcae /arith.c
parent835fbf4248cce666199f41a118befd1063fdea2e (diff)
downloadtxr-4355d30b13d462ab334380a3dd45258811d1690e.tar.gz
txr-4355d30b13d462ab334380a3dd45258811d1690e.tar.bz2
txr-4355d30b13d462ab334380a3dd45258811d1690e.zip
Fix more -fsanitize=implicit-conversion findings.
* arith.c (highest_significant_bit): Bugfix: do not pass a negative value to highest_bit, where we will get then get the wrong idea about the number of significant bits in the value, since the __builtin_clz primitives will include the sign bit. We want to complement the all the bits, so that the sign bit will go to zero. We can do this arithmetically by taking the additive inverse (which is the two's complement (which is the complement plus one)) and subtracting one. (ash): Avoid left shifting a negative number in HAVE_UBSAN mode using the same trick as in num_fast. * ffi.c (ffi_swap_u16): Here the shift and or calculation is producing a value beyond 16 bits which we are relying on the implicit conversion back to uin16_t to trim away. We add the cast to uint16_t to make it explicit. * hash.c (equal_hash): Also handle the CHR and NUM cases here via c_u like in eql_hash and eq_hash.
Diffstat (limited to 'arith.c')
-rw-r--r--arith.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/arith.c b/arith.c
index 200e6671..1159de96 100644
--- a/arith.c
+++ b/arith.c
@@ -464,7 +464,7 @@ static int highest_significant_bit(int_ptr_t n)
{
if (n >= 0)
return highest_bit(n);
- return highest_bit(n ^ INT_PTR_MAX);
+ return highest_bit(-n - 1);
}
void do_mp_error(val self, mp_err code)
@@ -3426,7 +3426,11 @@ val ash(val a, val bits)
cnum an = c_n(a);
int hb = highest_significant_bit(an);
if (bn + hb < num_bits) {
+#if HAVE_UBSAN
+ return num_fast(an * (convert(cnum, 1) << bn));
+#else
return num_fast(an << bn);
+#endif
} else {
val b = make_bignum();
mp_int tmp;