git: 61ed5748e4e9 - main - lib/libc/tests/string: improve memccpy "bounds" unit test

From: Robert Clausecker <fuz_at_FreeBSD.org>
Date: Sat, 14 Sep 2024 18:42:59 UTC
The branch main has been updated by fuz:

URL: https://cgit.FreeBSD.org/src/commit/?id=61ed5748e4e9c7397fcb2638b442f46ac5c9e7c5

commit 61ed5748e4e9c7397fcb2638b442f46ac5c9e7c5
Author:     Robert Clausecker <fuz@FreeBSD.org>
AuthorDate: 2024-07-19 20:50:28 +0000
Commit:     Robert Clausecker <fuz@FreeBSD.org>
CommitDate: 2024-09-14 18:42:19 +0000

    lib/libc/tests/string: improve memccpy "bounds" unit test
    
    The purpose of the "bounds" test is to check that the function does not
    overread the array bounds.  The old unit test, copied from the strlcpy()
    one, always ensured that we see the character c memccpy() is looking for
    in the source array before the array ends.  While this is correct for
    strlcpy(), memccpy()'s specification does not guarantee that c is
    present within the given size limit.
    
    The updated test handles this case better, ensuring that the source
    array ends early if c is not supposed to be present.
    
    Reported by:    getz
    Approved by:    emaste
    See also:       D46052
    Event:          GSoC 2024
    Differential Revision:  https://reviews.freebsd.org/D46051
---
 lib/libc/tests/string/memccpy_test.c | 50 ++++++++++++++++++++++++++----------
 1 file changed, 37 insertions(+), 13 deletions(-)

diff --git a/lib/libc/tests/string/memccpy_test.c b/lib/libc/tests/string/memccpy_test.c
index 82f4ef34af54..4784fee4ede5 100644
--- a/lib/libc/tests/string/memccpy_test.c
+++ b/lib/libc/tests/string/memccpy_test.c
@@ -1,6 +1,6 @@
 /*-
  * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
- * Copyright (c) 2023 The FreeBSD Foundation
+ * Copyright (c) 2023, 2024 The FreeBSD Foundation
  * All rights reserved.
  *
  * Portions of this software were developed by Robert Clausecker
@@ -54,34 +54,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_memccpy(const char *s)
+freebuf(char * buf, size_t len, int guard_at_end)
+{
+	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_memccpy(const char *s, size_t size)
 {
 	char *src, *dst, *expected;
-	size_t size, bufsize, x;
+	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 = NULL;
+				} else {
+					src = makebuf(size, i);
+					memcpy(src, s, size);
+					expected = dst + size;
+				}
+
 				memset(dst, 'X', bufsize);
-				expected = bufsize >= size ? dst + size : NULL;
-				assert(memccpy_fn(dst, src, src[size-1], bufsize) == expected);
-				assert(bufsize == 0 || strncmp(src, dst, bufsize - 1) == 0);
+				assert(memccpy_fn(dst, src, s[size-1], bufsize) == expected);
+				assert(memcmp(src, dst, MIN(bufsize, size)) == 0);
 				for (x = size; x < bufsize; x++)
 					assert(dst[x] == 'X');
+
+				freebuf(dst, bufsize, j);
+				freebuf(src, bufsize < size ? bufsize : size, i);
 			}
 		}
 	}
@@ -168,7 +191,8 @@ ATF_TC_BODY(bounds, tc)
 
 	for (i = 0; i < sizeof(buf) - 1; i++) {
 		buf[i] = ' ' + i;
-		test_memccpy(buf);
+		buf[i+1] = '\0';
+		test_memccpy(buf, i + 1);
 	}
 }