Skip to content

Commit 7526fd2

Browse files
committed
fix memmove large-length backward copy
F/1897
1 parent fefd74e commit 7526fd2

2 files changed

Lines changed: 35 additions & 3 deletions

File tree

src/string.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,14 +288,14 @@ void RAMFUNCTION *memcpy(void *dst, const void *src, size_t n)
288288
!defined(__CCRX__)
289289
void *memmove(void *dst, const void *src, size_t n)
290290
{
291-
int i;
291+
size_t i;
292292
if (dst == src)
293293
return dst;
294294
if (src < dst) {
295295
const char *s = (const char *)src;
296296
char *d = (char *)dst;
297-
for (i = n - 1; i >= 0; i--) {
298-
d[i] = s[i];
297+
for (i = n; i > 0; i--) {
298+
d[i - 1] = s[i - 1];
299299
}
300300
return dst;
301301
} else {

tools/unit-tests/unit-string.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@
2525
#define FAST_MEMCPY
2626

2727
#include <check.h>
28+
#include <limits.h>
2829
#include <stdint.h>
2930
#include <string.h>
31+
#ifdef __linux__
32+
#include <sys/mman.h>
33+
#endif
3034

3135
#include "string.c"
3236

@@ -325,6 +329,31 @@ START_TEST(test_memcpy_memmove)
325329
}
326330
END_TEST
327331

332+
#if defined(__linux__) && (SIZE_MAX > INT_MAX)
333+
START_TEST(test_memmove_large_overlap_length)
334+
{
335+
size_t n = (size_t)INT_MAX + 2U;
336+
size_t len = n + 1U;
337+
unsigned char *region = mmap(NULL, len, PROT_READ | PROT_WRITE,
338+
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
339+
340+
ck_assert_ptr_ne(region, MAP_FAILED);
341+
342+
region[0] = 0x11;
343+
region[1] = 0x22;
344+
region[n - 1] = 0x33;
345+
region[n] = 0x44;
346+
347+
memmove(region + 1, region, n);
348+
349+
ck_assert_uint_eq(region[1], 0x11);
350+
ck_assert_uint_eq(region[n], 0x33);
351+
352+
ck_assert_int_eq(munmap(region, len), 0);
353+
}
354+
END_TEST
355+
#endif
356+
328357
START_TEST(test_memcpy_aligned_buffers)
329358
{
330359
union {
@@ -443,6 +472,9 @@ Suite *string_suite(void)
443472
tcase_add_test(tcase_misc, test_strcpy_strncpy_strcat_strncat);
444473
tcase_add_test(tcase_misc, test_strncmp);
445474
tcase_add_test(tcase_misc, test_memcpy_memmove);
475+
#if defined(__linux__) && (SIZE_MAX > INT_MAX)
476+
tcase_add_test(tcase_misc, test_memmove_large_overlap_length);
477+
#endif
446478
tcase_add_test(tcase_misc, test_memcpy_aligned_buffers);
447479
tcase_add_test(tcase_misc, test_uart_writenum_basic);
448480
tcase_add_test(tcase_misc, test_uart_printf_formats);

0 commit comments

Comments
 (0)