diff --git a/librz/util/bitvector.c b/librz/util/bitvector.c index e34489d9b0..d27153661c 100644 --- a/librz/util/bitvector.c +++ b/librz/util/bitvector.c @@ -182,7 +182,7 @@ RZ_API ut32 rz_bv_copy(RZ_NONNULL const RzBitVector *src, RZ_NONNULL RzBitVector } /** - * Copy n bits from start position of source to start position of dest + * Copy n bits from start position of source to start position of dest, return num of copied bits * \param src RzBitVector, data source * \param src_start_pos ut32, start position in source bitvector of copy * \param dst RzBitVector, destination of copy @@ -202,7 +202,7 @@ RZ_API ut32 rz_bv_copy_nbits(RZ_NONNULL const RzBitVector *src, ut32 src_start_p } // normal case here - for (ut32 i = 0; i < max_nbit; ++i) { + for (ut32 i = 0; i < nbit; ++i) { bool c = rz_bv_get(src, src_start_pos + i); rz_bv_set(dst, dst_start_pos + i, c); } diff --git a/test/unit/test_bitvector.c b/test/unit/test_bitvector.c index a0f1fe3423..64dc0eb73c 100644 --- a/test/unit/test_bitvector.c +++ b/test/unit/test_bitvector.c @@ -1030,6 +1030,62 @@ static bool test_rz_bv_set_to_bytes_le(void) { mu_end; } +bool test_rz_bv_copy_nbits(void) { + const ut32 size = 20; + const ut32 part_sz = 8; + ut32 actual_copy = 0; + /// 1010 0000 0000 1111 1111 + RzBitVector *src = rz_bv_new(size); + for (ut32 i = 0; i < part_sz; ++i) { + rz_bv_set(src, i, true); + } + rz_bv_set(src, src->len - 1, true); + rz_bv_set(src, src->len - 3, true); + + /// copy part of bv to a new one with the same size + RzBitVector *small = rz_bv_new(part_sz); + actual_copy = rz_bv_copy_nbits(src, 0, small, 0, part_sz); + mu_assert_eq(actual_copy, part_sz, "copy part_sz to normal"); + mu_assert_streq_free(rz_bv_as_string(small), "11111111", "copy nbits small bv"); + + /// copy part of bv to a new one which has more spaces + RzBitVector *normal = rz_bv_new(size); + actual_copy = rz_bv_copy_nbits(src, 0, normal, 0, part_sz); + mu_assert_eq(actual_copy, part_sz, "copy part_sz bits to normal"); + mu_assert_streq_free(rz_bv_as_string(normal), "00000000000011111111", "copy nbits normal length bv"); + + /// copy part of bv to the medium + RzBitVector *res = rz_bv_new(size); + actual_copy = rz_bv_copy_nbits(src, 0, res, 8, part_sz); + mu_assert_eq(actual_copy, part_sz, "copy part_sz bits to medium"); + mu_assert_streq_free(rz_bv_as_string(res), "00001111111100000000", "copy nbits to medium"); + + /// copy non-zero, copy last 11 bits of `b` to the head of `a` + /// dst : a = 0001 0010 0011 ... + /// src : b = ... .001 1000 0110 + /// expect : 0011 0000 1101 ... = 0x30d45678 + RzBitVector *a = rz_bv_new_from_ut64(32, 0x12345678); + RzBitVector *b = rz_bv_new_from_ut64(32, 0x1986); + actual_copy = rz_bv_copy_nbits(b, 0, a, a->len - 11, 11); + mu_assert_eq(actual_copy, 11, "copy non-zero 11 bits"); + mu_assert_streq_free(rz_bv_as_hex_string(a, false), "0x30d45678", "copy non zero"); + + /// would fail (do nothing) if copy overflow is possible + RzBitVector *too_small = rz_bv_new(part_sz); + actual_copy = rz_bv_copy_nbits(src, 0, too_small, 0, part_sz + 2); + mu_assert_eq(actual_copy, 0, "copy 0 bits"); + mu_assert_true(rz_bv_is_zero_vector(too_small), "copy nothing"); + + rz_bv_free(src); + rz_bv_free(small); + rz_bv_free(normal); + rz_bv_free(res); + rz_bv_free(too_small); + rz_bv_free(a); + rz_bv_free(b); + mu_end; +} + bool all_tests() { mu_run_test(test_rz_bv_init32); mu_run_test(test_rz_bv_init64); @@ -1053,6 +1109,8 @@ bool all_tests() { mu_run_test(test_rz_bv_len_bytes); mu_run_test(test_rz_bv_set_all); mu_run_test(test_rz_bv_set_to_bytes_le); + mu_run_test(test_rz_bv_copy_nbits); + return tests_passed != tests_run; }