Module Name: src Committed By: riastradh Date: Wed Dec 28 15:34:19 UTC 2022
Modified Files: src/lib/libc/string: swab.c src/tests/lib/libc/string: t_swab.c Log Message: swab(3): Rewrite this to be understandable. And make the tests work, and exercise all lengths up to 100. Evidently the previous definition, presumably tightly optimized for 1980s-era compilers and CPUs, was too hard to understand, because it was incorrectly tested for two decades and broken for years. PR lib/57141 XXX pullup-8 XXX pullup-9 XXX pullup-10 To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/lib/libc/string/swab.c cvs rdiff -u -r1.2 -r1.3 src/tests/lib/libc/string/t_swab.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/string/swab.c diff -u src/lib/libc/string/swab.c:1.19 src/lib/libc/string/swab.c:1.20 --- src/lib/libc/string/swab.c:1.19 Wed Dec 28 14:32:04 2022 +++ src/lib/libc/string/swab.c Wed Dec 28 15:34:19 2022 @@ -1,11 +1,9 @@ -/* $NetBSD: swab.c,v 1.19 2022/12/28 14:32:04 kre Exp $ */ +/* $NetBSD: swab.c,v 1.20 2022/12/28 15:34:19 riastradh Exp $ */ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Jeffrey Mogul. + +/*- + * Copyright (c) 2022 The NetBSD Foundation, Inc. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -15,66 +13,58 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)swab.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: swab.c,v 1.19 2022/12/28 14:32:04 kre Exp $"); +__RCSID("$NetBSD: swab.c,v 1.20 2022/12/28 15:34:19 riastradh Exp $"); #endif -#endif /* LIBC_SCCS and not lint */ #include <assert.h> #include <unistd.h> void -swab(const void * __restrict from, void * __restrict to, ssize_t len) +swab(const void *__restrict src, void *__restrict dst, ssize_t nbytes) { - char temp; - const char *fp; - char *tp; - - if (len <= 1) - return; + const char *p = src; + char *q = dst; + size_t n; - _DIAGASSERT(from != NULL); - _DIAGASSERT(to != NULL); + _DIAGASSERT(src != NULL); + _DIAGASSERT(dst != NULL); - len /= 2; - fp = (const char *)from; - tp = (char *)to; -#define STEP temp = *fp++,*tp++ = *fp++,*tp++ = temp - - if (__predict_false(len == 1)) { - STEP; + if (nbytes <= 1) return; - } - /* round to multiple of 8 */ - while ((len % 8) != 0) - len--, STEP; - len /= 8; - if (len == 0) - return; - while (len-- != 0) { - STEP; STEP; STEP; STEP; - STEP; STEP; STEP; STEP; + /* + * Round nbytes/2 down; we ignore the last byte altogether if + * nbytes is odd. This way, if the destination array is + * uninitialized, sanitizers will recognize the last byte as + * still uninitialized and flag it as undefined. + */ + for (n = nbytes/2; n --> 0; p += 2, q += 2) { + /* + * According to POSIX (2018), the behaviour is + * undefined if src and dst overlap. However, there + * are uses in-tree (xsrc/external/mit/xfwp/dist/io.c) + * that rely on swab(ptr, ptr, n) to do the swabbing + * in-place. So make sure this works if src == dst. + */ + const char p0 = p[0], p1 = p[1]; + + q[0] = p1; + q[1] = p0; } } Index: src/tests/lib/libc/string/t_swab.c diff -u src/tests/lib/libc/string/t_swab.c:1.2 src/tests/lib/libc/string/t_swab.c:1.3 --- src/tests/lib/libc/string/t_swab.c:1.2 Thu Jul 7 08:27:36 2011 +++ src/tests/lib/libc/string/t_swab.c Wed Dec 28 15:34:19 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: t_swab.c,v 1.2 2011/07/07 08:27:36 jruoho Exp $ */ +/* $NetBSD: t_swab.c,v 1.3 2022/12/28 15:34:19 riastradh Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -39,15 +39,17 @@ #define MAXCHK 100 static void -build(char *a, char *b, size_t n) { +build(char *a, char *b, size_t n) +{ size_t i; - n >>= 1; for (i = 0; i < n; i += 2) { - b[i+1] = a[i] = (char)i; - b[i] = a[i+1] = (char)(i+1); + b[i + 1] = a[i] = (char)i; + b[i] = a[i + 1] = (char)(i + 1); } - for (n <<= 1; n < MAXCHK; n++) + if (n & 1) + a[n - 1] = b[n - 1] = (char)~1; + for (; n < MAXCHK; n++) a[n] = b[n] = (char)~0; } @@ -72,19 +74,23 @@ ATF_TC_BODY(swab_basic, tc) { char a[MAXCHK], b[MAXCHK], r[MAXCHK]; size_t i; + bool failed = false; - for (i = 0; i < MAXCHK; i += 2) { + for (i = 0; i < MAXCHK; i++) { build(a, b, i); (void)memset(r, ~0, MAXCHK); swab(a, r, i); + if (i & 1) /* last byte unspecified if odd length */ + r[i - 1] = (char )~1; if (memcmp(b, r, MAXCHK) != 0) { - fprintf(stderr, "pattern mismatch at %lu bytes", - (unsigned long)i); + printf("pattern mismatch at %zu bytes\n", i); dump("expect:", b, MAXCHK); dump("result:", r, MAXCHK); - atf_tc_fail("Check stderr for details"); + failed = true; } } + if (failed) + atf_tc_fail_nonfatal("Check stdout for details"); } ATF_TP_ADD_TCS(tp)