Jérémy Compostella has uploaded this change for review. ( https://review.coreboot.org/20535
Change subject: libpayload: Support unaligned pointer for memcpy, memmove and memcmp ......................................................................
libpayload: Support unaligned pointer for memcpy, memmove and memcmp
The memcpy(), memmove() and memcmp() functions use word by word operations regardless of the pointer alignment. Depending on the platform, this could lead to a crash.
This patch makes the memcpy(), memmove() or memcmp() operate byte per byte if they are supplied with unaligned pointers.
Change-Id: I0b668739b7b58d47266f10f2dff2dc9cbf38577e Signed-off-by: Jeremy Compostella jeremy.compostella@intel.com --- M payloads/libpayload/libc/memory.c 1 file changed, 20 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/35/20535/1
diff --git a/payloads/libpayload/libc/memory.c b/payloads/libpayload/libc/memory.c index 1adfb32..78418ba 100644 --- a/payloads/libpayload/libc/memory.c +++ b/payloads/libpayload/libc/memory.c @@ -66,13 +66,19 @@ size_t i; void *ret = dst;
+ if (!IS_ALIGNED((uintptr_t)dst, sizeof(unsigned long)) || + !IS_ALIGNED((uintptr_t)src, sizeof(unsigned long))) + goto copy_bytes; + for(i = 0; i < n / sizeof(unsigned long); i++) ((unsigned long *)dst)[i] = ((unsigned long *)src)[i];
src += i * sizeof(unsigned long); dst += i * sizeof(unsigned long); + n -= i * sizeof(unsigned long);
- for(i = 0; i < n % sizeof(unsigned long); i++) +copy_bytes: + for(i = 0; i < n ; i++) ((u8 *)dst)[i] = ((u8 *)src)[i];
return ret; @@ -88,6 +94,13 @@
if (src > dst) return memcpy(dst, src, n); + + if (!IS_ALIGNED((uintptr_t)dst, sizeof(unsigned long)) || + !IS_ALIGNED((uintptr_t)src, sizeof(unsigned long))) { + for (i = n - 1; i >= 0; i--) + ((u8 *)dst)[i] = ((u8 *)src)[i]; + return dst; + }
offs = n - (n % sizeof(unsigned long));
@@ -116,12 +129,17 @@
static int default_memcmp(const void *s1, const void *s2, size_t n) { - size_t i; + size_t i = 0; + + if (!IS_ALIGNED((uintptr_t)s1, sizeof(unsigned long)) || + !IS_ALIGNED((uintptr_t)s2, sizeof(unsigned long))) + goto compare_bytes;
for (i = 0; i < n / sizeof(unsigned long); i++) if (((unsigned long *)s1)[i] != ((unsigned long *)s2)[i]) break; /* fall through to find differing byte */
+compare_bytes: for (i *= sizeof(unsigned long); i < n; i++) if (((u8 *)s1)[i] != ((u8 *)s2)[i]) return ((u8 *)s1)[i] - ((u8 *)s2)[i];