From c3810c83aa9158e8903e23b51616f7d7faaa63bc Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Wed, 15 Jan 2014 18:22:34 +0000 Subject: [PATCH] Fix memmove and memcpy memmove needs to allow for overlapping memory regions and, together with memcpy, should return the input destination pointer, not the address after the end of the copied data. fixes ARM-software/tf-issues#18 Signed-off-by: Jon Medhurst --- lib/stdlib/mem.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/stdlib/mem.c b/lib/stdlib/mem.c index 145d651c..f1f335a6 100644 --- a/lib/stdlib/mem.c +++ b/lib/stdlib/mem.c @@ -63,29 +63,47 @@ int memcmp(const void *s1, const void *s2, size_t len) return 0; } - /* - * Move @len bytes from @src to @dst + * Copy @len bytes from @src to @dst */ -void *memmove(void *dst, const void *src, size_t len) +void *memcpy(void *dst, const void *src, size_t len) { const char *s = src; char *d = dst; while (len--) *d++ = *s++; - return d; + + return dst; } /* - * Copy @len bytes from @src to @dst + * Move @len bytes from @src to @dst */ -void *memcpy(void *dst, const void *src, size_t len) +void *memmove(void *dst, const void *src, size_t len) { - return memmove(dst, src, len); + /* + * The following test makes use of unsigned arithmetic overflow to + * more efficiently test the condition !(src <= dst && dst < str+len). + * It also avoids the situation where the more explicit test would give + * incorrect results were the calculation str+len to overflow (though + * that issue is probably moot as such usage is probably undefined + * behaviour and a bug anyway. + */ + if ((size_t)dst - (size_t)src >= len) { + /* destination not in source data, so can safely use memcpy */ + return memcpy(dst, src, len); + } else { + /* copy backwards... */ + const char *end = dst; + const char *s = (const char *)src + len; + char *d = (char *)dst + len; + while (d != end) + *--d = *--s; + } + return dst; } - /* * Scan @len bytes of @src for value @c */ -- 2.30.2