From e1096aa6530bfc22af53836ee8aed4381d818ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Battrel?= Date: Fri, 17 Jan 2025 07:44:17 +0100 Subject: [PATCH 1/3] include: util: Add `z_util_eq` and `z_util_memeq` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `z_util_eq` compare two memory areas and their length. It returns true if they are equal, else false. `z_util_memeq` the first n bytes of two memory areas. It returns true if they are equal, else false. Signed-off-by: Théo Battrel --- include/zephyr/sys/util.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/include/zephyr/sys/util.h b/include/zephyr/sys/util.h index 0e38acb4aae8..f8190178b168 100644 --- a/include/zephyr/sys/util.h +++ b/include/zephyr/sys/util.h @@ -28,6 +28,7 @@ #include #include #include +#include /** @brief Number of bits that make up a type */ #define NUM_BITS(t) (sizeof(t) * BITS_PER_BYTE) @@ -783,6 +784,40 @@ static inline void mem_xor_128(uint8_t dst[16], const uint8_t src1[16], const ui mem_xor_n(dst, src1, src2, 16); } +/** + * @brief Compare memory areas. The same way as `memcmp` it assume areas to be + * the same length + * + * @param m1 First memory area to compare, cannot be NULL even if length is 0 + * @param m2 Second memory area to compare, cannot be NULL even if length is 0 + * @param n First n bytes of @p m1 and @p m2 to compares + * + * @returns true if the @p n first bytes of @p m1 and @p m2 are the same, else + * false + */ +static inline bool z_util_memeq(const void *m1, const void *m2, size_t n) +{ + return memcmp(m1, m2, n) == 0; +} + +/** + * @brief Compare memory areas and their length + * + * If the length are 0, return true. + * + * @param m1 First memory area to compare, cannot be NULL even if length is 0 + * @param len1 Length of the first memory area to compare + * @param m2 Second memory area to compare, cannot be NULL even if length is 0 + * @param len2 Length of the second memory area to compare + * + * @returns true if both the length of the memory areas and their content are + * equal else false + */ +static inline bool z_util_eq(const void *m1, size_t len1, const void *m2, size_t len2) +{ + return len1 == len2 && z_util_memeq(m1, m2, len1); +} + #ifdef __cplusplus } #endif From bd1438479618dbf7b978610d083f49a40504ba4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Battrel?= Date: Fri, 17 Jan 2025 15:59:33 +0100 Subject: [PATCH 2/3] Tests: Util: Add unit tests for `z_util_eq`/`z_util_memeq` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two unit tests for the newly added functions `z_util_eq` and `z_util_memeq`. Signed-off-by: Théo Battrel --- tests/unit/util/main.c | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/unit/util/main.c b/tests/unit/util/main.c index e01c7dce2865..61c6e952897e 100644 --- a/tests/unit/util/main.c +++ b/tests/unit/util/main.c @@ -918,4 +918,55 @@ ZTEST(util, test_utf8_lcpy_null_termination) zassert_str_equal(dest_str, expected_result, "Failed to truncate"); } +ZTEST(util, test_z_util_eq) +{ + uint8_t src1[16]; + uint8_t src2[16]; + + bool mem_area_matching_1; + bool mem_area_matching_2; + + memset(src1, 0, sizeof(src1)); + memset(src2, 0, sizeof(src2)); + + for (size_t i = 0U; i < 16; i++) { + src1[i] = 0xAB; + src2[i] = 0xAB; + } + + src1[15] = 0xCD; + src2[15] = 0xEF; + + mem_area_matching_1 = z_util_eq(src1, sizeof(src1), src2, sizeof(src2)); + mem_area_matching_2 = z_util_eq(src1, sizeof(src1) - 1, src2, sizeof(src2) - 1); + + zassert_false(mem_area_matching_1); + zassert_true(mem_area_matching_2); +} + +ZTEST(util, test_z_util_memeq) +{ + uint8_t src1[16]; + uint8_t src2[16]; + uint8_t src3[16]; + + bool mem_area_matching_1; + bool mem_area_matching_2; + + memset(src1, 0, sizeof(src1)); + memset(src2, 0, sizeof(src2)); + + for (size_t i = 0U; i < 16; i++) { + src1[i] = 0xAB; + src2[i] = 0xAB; + src3[i] = 0xCD; + } + + mem_area_matching_1 = z_util_memeq(src1, src2, sizeof(src1)); + mem_area_matching_2 = z_util_memeq(src1, src3, sizeof(src1)); + + zassert_true(mem_area_matching_1); + zassert_false(mem_area_matching_2); +} + ZTEST_SUITE(util, NULL, NULL, NULL, NULL, NULL); From 6144a8532d73e9b81585d629c797f196d836bb51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Battrel?= Date: Tue, 21 Jan 2025 07:51:19 +0100 Subject: [PATCH 3/3] Bluetooth: Add usage of `z_util_eq` and `z_util_memeq` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update `bt_irk_eq` to use `z_util_memeq` instead of `memcmp` and the "disconnect" BabbleSim test to use `z_util_eq` instead of a first assertion on the size followed by a `memcmp`. This is done as an example usage of the two new functions. Signed-off-by: Théo Battrel --- subsys/bluetooth/host/keys.h | 3 ++- tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/host/keys.h b/subsys/bluetooth/host/keys.h index c1da17fb4881..dfeac2990018 100644 --- a/subsys/bluetooth/host/keys.h +++ b/subsys/bluetooth/host/keys.h @@ -9,6 +9,7 @@ #ifndef ZEPHYR_SUBSYS_BLUETOOTH_HOST_KEYS_H_ #define ZEPHYR_SUBSYS_BLUETOOTH_HOST_KEYS_H_ +#include #include /** @cond INTERNAL_HIDDEN */ @@ -54,7 +55,7 @@ struct bt_irk { static inline bool bt_irk_eq(struct bt_irk const *a, struct bt_irk const *b) { - return (memcmp(a->val, b->val, sizeof(a->val)) == 0); + return z_util_memeq(a->val, b->val, sizeof(a->val)); } struct bt_csrk { diff --git a/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c b/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c index 48923faa9805..97f42c1cc6bc 100644 --- a/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c +++ b/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -190,8 +191,7 @@ static void handle_att_write(struct net_buf *buf) static uint8_t ccc_write[2] = {0x03, 0x00}; - TEST_ASSERT(buf->len == 2, "unexpected write length: %d", buf->len); - TEST_ASSERT(memcmp(buf->data, ccc_write, sizeof(ccc_write)) == 0, "bad data"); + TEST_ASSERT(z_util_eq(buf->data, buf->len, ccc_write, sizeof(ccc_write)), "bad data\n"); send_write_rsp(); }