From 980d615401bb843a4ab64a7e376d9e042bb0dcb8 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 14 Feb 2022 06:39:54 -0800 Subject: 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. --- arith.c | 6 +++++- ffi.c | 2 +- hash.c | 3 +-- 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: -- cgit v1.2.3