git: 123c08620049 - main - libc/tests/string: improve stpncpy() "bounds" unit test

From: Robert Clausecker <fuz_at_FreeBSD.org>
Date: Sun, 14 Dec 2025 16:08:16 UTC
The branch main has been updated by fuz:

URL: https://cgit.FreeBSD.org/src/commit/?id=123c086200491819595abc271d360e605288fd18

commit 123c086200491819595abc271d360e605288fd18
Author:     Robert Clausecker <fuz@FreeBSD.org>
AuthorDate: 2025-12-04 16:34:59 +0000
Commit:     Robert Clausecker <fuz@FreeBSD.org>
CommitDate: 2025-12-14 16:05:30 +0000

    libc/tests/string: improve stpncpy() "bounds" unit test
    
    The test is extended the same way I previously extended the memccpy()
    test to fix what is probably the same kind of bug.
    
    PR:             291359
    Reported by:    Collin Funk <collin.funk1@gmail.com>
    Reviewed by:    ngie
    Approved by:    markj (mentor)
    Fixes:          6fa9e7d8737548ef93c573387ce62402c368d486 (D42519)
    See also:       61ed5748e4e9c7397fcb2638b442f46ac5c9e7c5 (D46051)
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D54169
    
    lib/libc/tests/string/stpncpy_test.c: apply ngie's fixes
---
 lib/libc/tests/string/stpncpy_test.c | 55 +++++++++++++++++++++++++-----------
 1 file changed, 39 insertions(+), 16 deletions(-)

diff --git a/lib/libc/tests/string/stpncpy_test.c b/lib/libc/tests/string/stpncpy_test.c
index 8574b2d591be..2dfd932d45dc 100644
--- a/lib/libc/tests/string/stpncpy_test.c
+++ b/lib/libc/tests/string/stpncpy_test.c
@@ -1,6 +1,6 @@
 /*-
  * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
- * Copyright (c) 2023 The FreeBSD Foundation
+ * Copyright (c) 2023, 2025 The FreeBSD Foundation
  * All rights reserved.
  *
  * Portions of this software were developed by Robert Clausecker
@@ -52,34 +52,57 @@ makebuf(size_t len, int guard_at_end)
 	buf = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
 	assert(buf);
 	if (guard_at_end) {
-		assert(munmap(buf + alloc_size - page_size, page_size) == 0);
+		assert(mprotect(buf + alloc_size - page_size, page_size, PROT_NONE) == 0);
 		return (buf + alloc_size - page_size - len);
 	} else {
-		assert(munmap(buf, page_size) == 0);
+		assert(mprotect(buf, page_size, PROT_NONE) == 0);
 		return (buf + page_size);
 	}
 }
 
 static void
-test_stpncpy(const char *s)
+freebuf(char *buf, size_t len, int guard_at_end)
 {
-	char *src, *dst;
-	size_t size, len, bufsize, x;
+	size_t alloc_size, page_size;
+
+	page_size = getpagesize();
+	alloc_size = roundup2(len, page_size) + page_size;
+
+	if (guard_at_end)
+		munmap(buf + len + page_size - alloc_size, alloc_size);
+	else
+		munmap(buf - page_size, alloc_size);
+}
+
+static void
+test_stpncpy(const char *s, size_t size)
+{
+	char *src, *dst, *expected;
+	size_t bufsize, x;
 	int i, j;
 
-	size = strlen(s) + 1;
 	for (i = 0; i <= 1; i++) {
 		for (j = 0; j <= 1; j++) {
-			for (bufsize = 0; bufsize <= size + 10; bufsize++) {
-				src = makebuf(size, i);
-				memcpy(src, s, size);
+			for (bufsize = 0; bufsize <= size + 32; bufsize++) {
 				dst = makebuf(bufsize, j);
+				if (bufsize < size) {
+					src = makebuf(bufsize, i);
+					memcpy(src, s, bufsize);
+					expected = dst + bufsize;
+				} else {
+					src = makebuf(size, i);
+					memcpy(src, s, size);
+					expected = dst + size - 1;
+				}
+
 				memset(dst, 'X', bufsize);
-				len = (bufsize < size) ? bufsize : size - 1;
-				assert(stpncpy_fn(dst, src, bufsize) == dst+len);
-				assert(memcmp(src, dst, len) == 0);
-				for (x = len; x < bufsize; x++)
+				assert(stpncpy_fn(dst, src, bufsize) == expected);
+				assert(memcmp(src, dst, MIN(bufsize, size)) == 0);
+				for (x = size; x < bufsize; x++)
 					assert(dst[x] == '\0');
+
+				freebuf(dst, bufsize, j);
+				freebuf(src, MIN(bufsize, size));
 			}
 		}
 	}
@@ -140,12 +163,12 @@ ATF_TC_WITHOUT_HEAD(bounds);
 ATF_TC_BODY(bounds, tc)
 {
 	size_t i;
-	char buf[64+1];
+	char buf[64];
 
 	for (i = 0; i < sizeof(buf) - 1; i++) {
 		buf[i] = ' ' + i;
 		buf[i+1] = '\0';
-		test_stpncpy(buf);
+		test_stpncpy(buf, i + 2);
 	}
 }