Skip to content

Commit bb00bc0

Browse files
memmove for overlaping memory (ros2#434) (ros2#437)
* memmove for overlaping memory * Add test for memcpy to memmove Signed-off-by: Tyler Weaver <[email protected]> (cherry picked from commit 5b99aad) Co-authored-by: Tyler Weaver <[email protected]>
1 parent 2d9d74e commit bb00bc0

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

src/array_list.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,11 @@ rcutils_array_list_remove(rcutils_array_list_t * array_list, size_t index)
172172
if (copy_count > 0) {
173173
uint8_t * dst_ptr = rcutils_array_list_get_pointer_for_index(array_list, index);
174174
uint8_t * src_ptr = rcutils_array_list_get_pointer_for_index(array_list, index + 1);
175-
memcpy(dst_ptr, src_ptr, array_list->impl->data_size * copy_count);
175+
// If the size of the list is >1 the regions of memory overlap.
176+
// POSIX and C standards are explicit that employing memcpy() with overlapping
177+
// areas produces undefined behavior. The recomendation is to use memmove.
178+
// Reference: https://man7.org/linux/man-pages/man3/memcpy.3.html
179+
memmove(dst_ptr, src_ptr, array_list->impl->data_size * copy_count);
176180
}
177181

178182
array_list->impl->size--;

test/test_array_list.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,30 @@ TEST_F(ArrayListPreInitTest, remove_success_removes_from_list) {
248248
EXPECT_EQ(size, (size_t)0);
249249
}
250250

251+
TEST_F(ArrayListPreInitTest, remove_success_removes_from_list_with_multiple_items) {
252+
uint32_t data = 22;
253+
size_t index = 0;
254+
size_t size = 0;
255+
rcutils_ret_t ret = RCUTILS_RET_OK;
256+
257+
// Add a few things first so we know the index isn't out of bounds
258+
for (size_t i = 0; i < 3; ++i) {
259+
ret = rcutils_array_list_add(&list, &data);
260+
ASSERT_EQ(RCUTILS_RET_OK, ret) << rcutils_get_error_string().str;
261+
}
262+
263+
ret = rcutils_array_list_get_size(&list, &size);
264+
ASSERT_EQ(RCUTILS_RET_OK, ret) << rcutils_get_error_string().str;
265+
EXPECT_EQ(size, (size_t)3);
266+
267+
ret = rcutils_array_list_remove(&list, index);
268+
ASSERT_EQ(RCUTILS_RET_OK, ret) << rcutils_get_error_string().str;
269+
270+
ret = rcutils_array_list_get_size(&list, &size);
271+
ASSERT_EQ(RCUTILS_RET_OK, ret) << rcutils_get_error_string().str;
272+
EXPECT_EQ(size, (size_t)2);
273+
}
274+
251275
TEST_F(ArrayListTest, get_list_null_fails) {
252276
size_t index = 0;
253277
uint32_t data = 0;

0 commit comments

Comments
 (0)