Module Name:    src
Committed By:   martin
Date:           Wed Feb 22 18:47:00 UTC 2023

Modified Files:
        src/lib/libc/string [netbsd-10]: swab.c
        src/tests/lib/libc/string [netbsd-10]: t_swab.c

Log Message:
Pull up following revision(s) (requested by riastradh in ticket #98):

        tests/lib/libc/string/t_swab.c: revision 1.3
        lib/libc/string/swab.c: revision 1.20

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


To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.18.56.1 src/lib/libc/string/swab.c
cvs rdiff -u -r1.2 -r1.2.52.1 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.18 src/lib/libc/string/swab.c:1.18.56.1
--- src/lib/libc/string/swab.c:1.18	Tue Jan  4 17:14:07 2011
+++ src/lib/libc/string/swab.c	Wed Feb 22 18:47:00 2023
@@ -1,11 +1,9 @@
-/*	$NetBSD: swab.c,v 1.18 2011/01/04 17:14:07 martin Exp $	*/
+/*	$NetBSD: swab.c,v 1.18.56.1 2023/02/22 18:47:00 martin 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.18 2011/01/04 17:14:07 martin Exp $");
+__RCSID("$NetBSD: swab.c,v 1.18.56.1 2023/02/22 18:47:00 martin 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)
-		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.2.52.1
--- 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 Feb 22 18:46:59 2023
@@ -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.2.52.1 2023/02/22 18:46:59 martin 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)

Reply via email to