From 4213ddfecc0003796a63cfa0068fa1f5ffbd4476 Mon Sep 17 00:00:00 2001 From: Rot127 <45763064+Rot127@users.noreply.github.com> Date: Thu, 8 Jan 2026 13:47:53 +0000 Subject: [PATCH] Fix reachable invalid state, for bitvector in-place casts from large to large. (#5746) --- librz/util/bitvector.c | 22 ++++++++++++++++------ test/unit/test_bitvector.c | 9 +++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/librz/util/bitvector.c b/librz/util/bitvector.c index 6361c59bcc..21991a0714 100644 --- a/librz/util/bitvector.c +++ b/librz/util/bitvector.c @@ -2082,16 +2082,26 @@ RZ_API bool rz_bv_cast_inplace(RZ_INOUT RZ_NONNULL RzBitVector *bv, ut32 to_size // The bit vector needs a larger buffer. resize_large_a(bv, NELEM(to_size, BV_ELEM_SIZE)); } + size_t old_size = bv->len; if (bv->len <= 64) { - // This was a small bit vector and now is a large one. - // Copy bits to the buffer. - bv_copy_nbits_small_to_large(bv, 0, bv, 0, bv->len); + if (bv_copy_nbits_small_to_large(bv, 0, bv, 0, old_size) != old_size) { + return false; + } + } else if (to_size <= 64) { + if (bv_copy_nbits_large_to_small(bv, 0, bv, 0, to_size) != to_size) { + return false; + } + } else if (to_size >= old_size) { + if (bv_copy_nbits_large_aligned(bv, 0, bv, 0, old_size) != old_size) { + return false; + } } else { - bv_copy_nbits_large_to_small(bv, 0, bv, 0, to_size); + if (bv_copy_nbits_large_aligned(bv, 0, bv, 0, to_size) != to_size) { + return false; + } } - size_t old_len = bv->len; bv->len = to_size; - rz_bv_set_range(bv, old_len, to_size - 1, fill_bit); + rz_bv_set_range(bv, old_size, to_size - 1, fill_bit); return true; } diff --git a/test/unit/test_bitvector.c b/test/unit/test_bitvector.c index 9ba546928b..8a3909a752 100644 --- a/test/unit/test_bitvector.c +++ b/test/unit/test_bitvector.c @@ -1370,6 +1370,7 @@ bool test_rz_bv_cast_inplace(void) { mu_assert_notnull(small->bits.large_a, "Buffer not set"); mu_assert_eq(small->_elem_len, 9, "Buffer length wrong"); + // Cast large to small mu_assert_true(rz_bv_cast_inplace(large, 32, true), "Cast failed"); mu_assert_eq(rz_bv_to_ut64(large), 0x0c0d0e0f, "Mismatch after cast"); mu_assert_streq_free(rz_bv_as_hex_string(large, true), "0x0c0d0e0f", "small to large cast failed"); @@ -1377,12 +1378,20 @@ bool test_rz_bv_cast_inplace(void) { mu_assert_notnull(large->bits.large_a, "Buffer not set"); mu_assert_eq(large->_elem_len, 16, "Buffer length wrong"); + // Cast small to large mu_assert_true(rz_bv_cast_inplace(large, 256, true), "Cast failed"); mu_assert_streq_free(rz_bv_as_hex_string(large, false), "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff0c0d0e0f", "small to large cast failed"); mu_assert_eq(large->len, 256, "New size is off"); mu_assert_notnull(large->bits.large_a, "Buffer not set"); mu_assert_eq(large->_elem_len, 32, "Buffer length wrong"); + // Cast large 256 bit to 128 bit. + mu_assert_true(rz_bv_cast_inplace(large, 128, true), "Cast failed"); + mu_assert_streq_free(rz_bv_as_hex_string(large, false), "0xffffffffffffffffffffffff0c0d0e0f", "large to large cast failed"); + mu_assert_eq(large->len, 128, "New size is off"); + mu_assert_notnull(large->bits.large_a, "Buffer not set"); + mu_assert_eq(large->_elem_len, 32, "Buffer length wrong"); + rz_bv_free(small); rz_bv_free(large); mu_end;