aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Medhurst <tixy@linaro.org>2014-01-15 18:22:34 +0000
committerDan Handley <dan.handley@arm.com>2014-01-30 17:55:31 +0000
commitc3810c83aa9158e8903e23b51616f7d7faaa63bc (patch)
tree43f72a46a19f54ded3d0650a668681620a4d5ad0
parent36eaaf37690c1019c99335e708361b5a613101db (diff)
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 <tixy@linaro.org>
-rw-r--r--lib/stdlib/mem.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/lib/stdlib/mem.c b/lib/stdlib/mem.c
index 145d651..f1f335a 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
*/