Skip to content

Commit eca76ef

Browse files
committed
string: fix unaligned backward word copies
1 parent a5ef464 commit eca76ef

2 files changed

Lines changed: 16 additions & 5 deletions

File tree

src/string.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -294,17 +294,20 @@ void *memmove(void *dst, const void *src, size_t n)
294294
if (src < dst) {
295295
const char *s = (const char *)src;
296296
char *d = (char *)dst;
297+
size_t aligned_n = 0;
297298
if (((size_t)dst & (sizeof(unsigned long)-1)) == 0 &&
298299
((size_t)src & (sizeof(unsigned long)-1)) == 0)
299300
{
300-
while (n >= sizeof(unsigned long)) {
301-
n -= sizeof(unsigned long);
302-
*(unsigned long*)(d + n) = *(const unsigned long*)(s + n);
303-
}
301+
aligned_n = n & ~(sizeof(unsigned long) - 1);
304302
}
305-
for (i = n; i > 0; i--) {
303+
for (i = n; i > aligned_n; i--) {
306304
d[i - 1] = s[i - 1];
307305
}
306+
while (aligned_n > 0) {
307+
aligned_n -= sizeof(unsigned long);
308+
*(unsigned long*)(d + aligned_n) =
309+
*(const unsigned long*)(s + aligned_n);
310+
}
308311
return dst;
309312
} else {
310313
return memcpy(dst, src, n);

tools/unit-tests/unit-string.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,14 @@ START_TEST(test_memcpy_memmove)
325325
ck_assert_int_eq(p[0], 0);
326326
ck_assert_int_eq(p[1], 1);
327327

328+
for (i = 0; i < 24; i++) {
329+
p[i] = (unsigned char)i;
330+
}
331+
memmove(p + sizeof(unsigned long), p, sizeof(unsigned long) + 2);
332+
for (i = 0; i < (int)(sizeof(unsigned long) + 2); i++) {
333+
ck_assert_int_eq(p[sizeof(unsigned long) + i], i);
334+
}
335+
328336
ck_assert_ptr_eq(memmove(p, p, 4), p);
329337
}
330338
END_TEST

0 commit comments

Comments
 (0)