Files
src/lib/libc/string/swab.c
T
John Baldwin 2a5c5b8f7c swab: Correctly treat the data as misaligned
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
2026-01-14 12:10:33 -05:00

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;
}
}