diff --git a/lib/libc/string/swab.c b/lib/libc/string/swab.c --- a/lib/libc/string/swab.c +++ b/lib/libc/string/swab.c @@ -4,19 +4,22 @@ */ #include +#include void swab(const void * __restrict from, void * __restrict to, ssize_t len) { - const unsigned char *f = from; - unsigned char *t = to; + const uint16_t *f __aligned(1) = from; + uint16_t *t __aligned(1) = to; + /* + * POSIX says overlapping copy behavior is undefined, however many + * applications assume the old FreeBSD and current GNU libc behavior + * that will swap the bytes correctly when from == to. Reading both bytes + * and swapping them before writing them back accomplishes this. + */ while (len > 1) { - t[0] = f[1]; - t[1] = f[0]; - - f += 2; - t += 2; + *t++ = bswap16(*f++); len -= 2; } }