Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions include/zenoh-pico/protocol/iobuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,11 @@ static inline void _z_iosli_read_bytes(_z_iosli_t *ios, uint8_t *dst, size_t off
static inline void _z_iosli_copy_bytes(_z_iosli_t *dst, const _z_iosli_t *src) {
size_t length = _z_iosli_readable(src);
assert(dst->_capacity >= length);
(void)memcpy(dst->_buf + dst->_w_pos, src->_buf + src->_r_pos, length);
dst->_w_pos += length;
// SAFETY: Checked by assert above.
// Flawfinder: ignore [CWE-120]
(void)memcpy(dst->_buf, src->_buf + src->_r_pos, length);
dst->_r_pos = 0;
dst->_w_pos = length;
}
static inline void _z_iosli_write_bytes(_z_iosli_t *ios, const uint8_t *bs, size_t offset, size_t length) {
assert(_z_iosli_writable(ios) >= length);
Expand Down
5 changes: 5 additions & 0 deletions src/protocol/iobuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ void _z_iosli_copy(_z_iosli_t *dst, const _z_iosli_t *src) {
dst->_buf = (uint8_t *)z_malloc(src->_capacity);
if (dst->_buf != NULL) {
(void)memcpy(dst->_buf, src->_buf, src->_capacity);
} else {
dst->_r_pos = 0;
dst->_w_pos = 0;
dst->_capacity = 0;
dst->_is_alloc = false;
}
} else {
dst->_buf = src->_buf;
Expand Down
92 changes: 92 additions & 0 deletions tests/z_iobuf_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,95 @@ void test_wbuf_wrap_bytes(void) {
printf("Ok\n");
}

static void fill_pattern(uint8_t *buf, size_t n) {
for (size_t i = 0; i < n; i++) {
buf[i] = (uint8_t)(0xA0u + (uint8_t)i);
}
}

void test_copy_bytes_readable_region(void) {
_z_iosli_t src = _z_iosli_make(16);
_z_iosli_t dst = _z_iosli_make(16);
assert(src._buf);
assert(dst._buf);

fill_pattern(src._buf, src._capacity);

// Make readable window be [r_pos..w_pos) = [5..12) => length 7
src._r_pos = 5;
src._w_pos = 12;

// Dirty dst positions to ensure function overwrites them
dst._r_pos = 3;
dst._w_pos = 9;
memset(dst._buf, 0x00, dst._capacity);

_z_iosli_copy_bytes(&dst, &src);

// dst now contains exactly the readable bytes starting at offset 0
assert(dst._r_pos == 0);
assert(dst._w_pos == 7);
assert(memcmp(dst._buf, src._buf + src._r_pos, 7) == 0);

_z_iosli_clear(&src);
_z_iosli_clear(&dst);
}

void test_copy_bytes_exact_capacity_fit(void) {
_z_iosli_t src = _z_iosli_make(32);
assert(src._buf);

// Create a readable region length = 10
src._r_pos = 2;
src._w_pos = 12; // len = 10
fill_pattern(src._buf, src._capacity);

_z_iosli_t dst = _z_iosli_make(10);
assert(dst._buf);
memset(dst._buf, 0xEE, dst._capacity);

// Should succeed because dst capacity == readable length
_z_iosli_copy_bytes(&dst, &src);

assert(dst._r_pos == 0);
assert(dst._w_pos == 10);
assert(memcmp(dst._buf, src._buf + src._r_pos, 10) == 0);

_z_iosli_clear(&src);
_z_iosli_clear(&dst);
}

void test_copy_bytes_does_not_alias(void) {
_z_iosli_t src = _z_iosli_make(16);
_z_iosli_t dst = _z_iosli_make(16);
assert(src._buf && dst._buf);

fill_pattern(src._buf, src._capacity);
src._r_pos = 4;
src._w_pos = 9; // len = 5

_z_iosli_copy_bytes(&dst, &src);

assert(dst._r_pos == 0);
assert(dst._w_pos == 5);
assert(memcmp(dst._buf, src._buf + src._r_pos, 5) == 0);

// Mutate src readable region; dst should remain unchanged (deep copy)
src._buf[src._r_pos + 0] ^= 0xFF;
src._buf[src._r_pos + 1] ^= 0xFF;

// Should differ
assert(memcmp(dst._buf, src._buf + src._r_pos, 5) != 0);

// But dst still equals original pattern:
uint8_t expected_full[16];
fill_pattern(expected_full, sizeof(expected_full));
assert(memcmp(dst._buf, expected_full + 4, 5) == 0);

_z_iosli_clear(&src);
_z_iosli_clear(&dst);
}

/*=============================*/
/* Main */
/*=============================*/
Expand All @@ -634,4 +723,7 @@ int main(void) {
wbuf_reusable_write_zbuf_read();
}
test_wbuf_wrap_bytes();
test_copy_bytes_readable_region();
test_copy_bytes_exact_capacity_fit();
test_copy_bytes_does_not_alias();
}
Loading