diff --git a/src/snmalloc/global/memcpy.h b/src/snmalloc/global/memcpy.h index 9376be975..0e2eb23d9 100644 --- a/src/snmalloc/global/memcpy.h +++ b/src/snmalloc/global/memcpy.h @@ -494,7 +494,7 @@ namespace snmalloc return report_fatal_bounds_error( dst, len, "memmove with destination out of bounds of heap allocation"); - if (dst > src) + if ((address_cast(dst) - address_cast(src)) < len) { // slow 'safe' reverse copy, we avoid optimised rollouts // to cope with typical memmove use cases, moving diff --git a/src/snmalloc/override/memcpy.cc b/src/snmalloc/override/memcpy.cc index de26263a6..ec6804041 100644 --- a/src/snmalloc/override/memcpy.cc +++ b/src/snmalloc/override/memcpy.cc @@ -6,7 +6,7 @@ extern "C" * Snmalloc checked memcpy. */ SNMALLOC_EXPORT void* - SNMALLOC_NAME_MANGLE(memcpy)(void* dst, const void* src, size_t len) + SNMALLOC_NAME_MANGLE(memcpy)(void* dst, const void* src, size_t len) { return snmalloc::memcpy(dst, src, len); } @@ -15,7 +15,7 @@ extern "C" * Snmalloc checked memmove. */ SNMALLOC_EXPORT void* - SNMALLOC_NAME_MANGLE(memmove)(void* dst, const void* src, size_t len) + SNMALLOC_NAME_MANGLE(memmove)(void* dst, const void* src, size_t len) { return snmalloc::memmove(dst, src, len); } diff --git a/src/test/func/memcpy/func-memcpy.cc b/src/test/func/memcpy/func-memcpy.cc index 7d16206d5..dbedf8fb9 100644 --- a/src/test/func/memcpy/func-memcpy.cc +++ b/src/test/func/memcpy/func-memcpy.cc @@ -160,11 +160,11 @@ void check_bounds(size_t size, size_t out_of_bounds) my_free(d); } -void check_overlaps(size_t size) +void check_overlaps1() { - START_TEST("memmove overlaps, size {}", size); + size_t size = 16; + START_TEST("memmove overlaps1"); auto* s = static_cast(my_malloc(size * sizeof(unsigned int))); - auto sz = size / 2; for (size_t i = 0; i < size; ++i) { s[i] = static_cast(i); @@ -177,16 +177,29 @@ void check_overlaps(size_t size) my_memmove(ptr, s, size * sizeof(s[0])); EXPECT(ptr == s, "overlap error: {} {}", ptr, s); my_free(s); - s = static_cast(my_malloc(size * sizeof(unsigned int))); +} + +template +void check_overlaps2(size_t size) +{ + START_TEST("memmove overlaps2, size {}", size); + auto sz = size / 2; + auto offset = size / 2; + auto* s = static_cast(my_malloc(size * sizeof(unsigned int))); for (size_t i = 0; i < size; ++i) { s[i] = static_cast(i); } - ptr = s + sz; - my_memmove(ptr, s, sz * sizeof(unsigned int)); - for (size_t i = 0; i < sz; ++i) + auto dst = after ? s + offset : s; + auto src = after ? s : s + offset; + size_t i = after ? 0 : offset; + size_t u = 0; + my_memmove(dst, src, sz * sizeof(unsigned int)); + while (u < sz) { - EXPECT(ptr[i] == s[i], "overlap error: {} {}", ptr[i], s[i]); + EXPECT(dst[u] == i, "overlap error: {} {}", dst[u], i); + u++; + i++; } my_free(s); } @@ -223,9 +236,12 @@ int main() check_size(x); } - for (size_t x = 8; x < 256; x += 8) + check_overlaps1(); + + for (size_t x = 8; x < 256; x += 64) { - check_overlaps(x); + check_overlaps2(x); + check_overlaps2(x); } } #endif