diff --git a/librz/util/bitvector.c b/librz/util/bitvector.c index bed7ec5194..15eb49e003 100644 --- a/librz/util/bitvector.c +++ b/librz/util/bitvector.c @@ -1810,14 +1810,10 @@ RZ_API bool rz_bv_set_from_ut64(RZ_NONNULL RzBitVector *bv, ut64 value) { bv->bits.small_u &= (UT64_MAX >> (64 - bv->len)); return true; } - if (value == 0) { - memset(bv->bits.large_a, 0, bv->_elem_len); - return true; - } - for (ut32 i = 0; i < bv->len; ++i) { - rz_bv_set(bv, i, value & 1); - value >>= 1; + memset(bv->bits.large_a, 0, bv->_elem_len); + for (size_t i = 0; i < 8 && value; ++i, value >>= 8) { + bv->bits.large_a[i] = value & 0xff; } return true; } @@ -1839,10 +1835,21 @@ RZ_API bool rz_bv_set_from_st64(RZ_NONNULL RzBitVector *bv, st64 value) { return true; } - for (ut32 i = 0; i < bv->len; ++i) { - rz_bv_set(bv, i, value & 1); - value >>= 1; + ut64 uval = (ut64)value; + for (size_t i = 0; i < 8; ++i, uval >>= 8) { + bv->bits.large_a[i] = uval & 0xff; } + if (value >= 0) { + memset(bv->bits.large_a + 8, 0x00, bv->_elem_len - 8); + return true; + } + + memset(bv->bits.large_a + 8, 0xff, bv->_elem_len - 8 - 1); + + // set high bits + size_t min_bytes_needed = ((bv->len + 7) / 8); + size_t unset_bits = (min_bytes_needed * 8) - bv->len; + bv->bits.large_a[min_bytes_needed - 1] = 0xff >> unset_bits; return true; } diff --git a/test/unit/test_bitvector.c b/test/unit/test_bitvector.c index 793d188cfb..2d1b53edfd 100644 --- a/test/unit/test_bitvector.c +++ b/test/unit/test_bitvector.c @@ -87,17 +87,6 @@ bool test_rz_bv_init128(void) { s = rz_bv_as_hex_string(bits, true); mu_assert_streq_free(s, "0x00000000000000000000000000000064", "string hex value of bv"); - rz_bv_set_from_ut64(bits, 0); - mu_assert_eq(rz_bv_to_ut64(bits), 0, "Did not set to zero"); - - rz_bv_set(bits, 2, true); - rz_bv_set(bits, 5, true); - rz_bv_set(bits, 6, true); - mu_assert("new from 128", is_equal_bv(bits, bits_cmp)); - - rz_bv_set_from_st64(bits, 0); - mu_assert_eq(rz_bv_to_ut64(bits), 0, "Did not set to zero"); - rz_bv_free(bits); rz_bv_free(bits_cmp); rz_bv_free(bits_dup); @@ -187,6 +176,54 @@ bool test_rz_bv_init_signed(void) { mu_end; } +bool test_rz_bv_set_from(void) { + char *s = NULL; + + RzBitVector *bits_128 = rz_bv_new_from_ut64(128, 100); + RzBitVector *bits_128_cmp = rz_bv_new(128); + rz_bv_set(bits_128_cmp, 2, true); + rz_bv_set(bits_128_cmp, 5, true); + rz_bv_set(bits_128_cmp, 6, true); + + rz_bv_set_from_ut64(bits_128, 0); + mu_assert_eq(rz_bv_to_ut64(bits_128), 0, "Did not set to zero"); + + rz_bv_set(bits_128, 2, true); + rz_bv_set(bits_128, 5, true); + rz_bv_set(bits_128, 6, true); + mu_assert("new from 128", is_equal_bv(bits_128, bits_128_cmp)); + + rz_bv_set_from_st64(bits_128, 0); + mu_assert_eq(rz_bv_to_ut64(bits_128), 0, "Did not set to zero"); + + rz_bv_set(bits_128, 2, true); + rz_bv_set(bits_128, 67, true); + rz_bv_set_from_ut64(bits_128, 0x7766554433221100ull); + s = rz_bv_as_hex_string(bits_128, true); + mu_assert_streq_free(s, "0x00000000000000007766554433221100", "string hex value of bv"); + + rz_bv_set_from_st64(bits_128, (st64)0xffeeddccbbaa9988ull); + s = rz_bv_as_hex_string(bits_128, true); + mu_assert_streq_free(s, "0xffffffffffffffffffeeddccbbaa9988", "string hex value of bv"); + + rz_bv_free(bits_128); + rz_bv_free(bits_128_cmp); + + RzBitVector *bits_67 = rz_bv_new_from_st64(67, -1); + s = rz_bv_as_hex_string(bits_67, true); + mu_assert_streq_free(s, "0x07ffffffffffffffff", "string hex value of bv"); + rz_bv_cast_inplace(bits_67, 69, rz_bv_msb(bits_67)); + s = rz_bv_as_hex_string(bits_67, true); + mu_assert_streq_free(s, "0x1fffffffffffffffff", "string hex value of bv"); + rz_bv_set_from_st64(bits_67, 9); + s = rz_bv_as_hex_string(bits_67, false); + mu_assert_streq_free(s, "0x9", "string hex value of bv"); + + rz_bv_free(bits_67); + + mu_end; +} + bool test_rz_bv_logic_large(void) { RzBitVector *x, *y, *z; RzBitVector *result; @@ -1986,6 +2023,7 @@ bool all_tests() { mu_run_test(test_rz_bv_init128); mu_run_test(test_rz_bv_init70); mu_run_test(test_rz_bv_init_signed); + mu_run_test(test_rz_bv_set_from); mu_run_test(test_rz_bv_cmp); mu_run_test(test_rz_bv_eq); mu_run_test(test_rz_bv_cast);