summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--arith.c6
-rw-r--r--ffi.c2
-rw-r--r--hash.c3
3 files changed, 7 insertions, 4 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;
diff --git a/ffi.c b/ffi.c
index 8388b5cf..63fdf45a 100644
--- a/ffi.c
+++ b/ffi.c
@@ -942,7 +942,7 @@ static val ffi_val_get(struct txr_ffi_type *tft, mem_t *src, val self)
static u16_t ffi_swap_u16(u16_t n)
{
- return (n << 8 | n >> 8);
+ return convert(u16_t, n << 8 | n >> 8);
}
static u32_t ffi_swap_u32(u32_t n)
diff --git a/hash.c b/hash.c
index 1a481061..abefdf24 100644
--- a/hash.c
+++ b/hash.c
@@ -317,9 +317,8 @@ ucnum equal_hash(val obj, int *count, ucnum seed)
case STR:
return hash_c_str(obj->st.str, seed, count);
case CHR:
- return c_chr(obj);
case NUM:
- return c_num(obj, self);
+ return c_u(obj);
case SYM:
case PKG:
case ENV: