2a5c5b8f7c
The __aligned attribute in the previous version applied to the location
of the pointers, not the data the pointers pointed to. While this
could be fixed by applying the attribute to a local typedef of uint16_t,
just using memcpy() for the unaligned access is simpler and ISO C.
This fixes the build on CHERI architectures which do not support
misaligned pointers and were thus failing with:
lib/libc/string/swab.c:12:18: error: alignment (1) of 'const uint16_t *' (aka 'const unsigned short *') is less than the required capability alignment (16) [-Werror,-Wcheri-capability-misuse]
12 | const uint16_t *f __aligned(1) = from;
|
Co-authored by: Jessica Clarke <jrtc27@FreeBSD.org>
Fixes: 02ebbc781f ("swab: Fix implementation to support overlapping copies")
Sponsored by: AFRL, DARPA
Reviewed by: markj
Differential Revision: https://reviews.freebsd.org/D54399
33 lines
709 B
C
33 lines
709 B
C
/*-
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
* Copyright (c) 2024 rilysh <nightquick@proton.me>
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/endian.h>
|
|
|
|
void
|
|
swab(const void * __restrict from, void * __restrict to, ssize_t len)
|
|
{
|
|
const char *f = from;
|
|
char *t = to;
|
|
uint16_t tmp;
|
|
|
|
/*
|
|
* 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) {
|
|
memcpy(&tmp, f, 2);
|
|
tmp = bswap16(tmp);
|
|
memcpy(t, &tmp, 2);
|
|
|
|
f += 2;
|
|
t += 2;
|
|
len -= 2;
|
|
}
|
|
}
|