From 6fa9e7d8737548ef93c573387ce62402c368d486 Mon Sep 17 00:00:00 2001 From: Robert Clausecker Date: Sun, 5 Nov 2023 00:02:00 -0400 Subject: [PATCH] lib/libc/tests/string/stpncpy_test.c: extend for upcoming SSE implementation This adds additional unit tests validating the function for All possible alignment offsets of source and destination. Also extend the test to allow testing of an external stpncpy implementation, which greatly simplifies the development of custom implementations. Sponsored by: The FreeBSD Foundation Tested by: developers@, exp-run Approved by: mjg MFC after: 1 month MFC to: stable/14 PR: 275785 Differential Revision: https://reviews.freebsd.org/D42519 --- lib/libc/tests/string/stpncpy_test.c | 99 ++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 14 deletions(-) diff --git a/lib/libc/tests/string/stpncpy_test.c b/lib/libc/tests/string/stpncpy_test.c index 8154237eb8c..8574b2d591b 100644 --- a/lib/libc/tests/string/stpncpy_test.c +++ b/lib/libc/tests/string/stpncpy_test.c @@ -1,7 +1,11 @@ /*- * Copyright (c) 2009 David Schultz + * Copyright (c) 2023 The FreeBSD Foundation * All rights reserved. * + * Portions of this software were developed by Robert Clausecker + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -27,12 +31,15 @@ #include #include #include +#include #include #include #include #include +static char *(*stpncpy_fn)(char *restrict, const char *restrict, size_t); + static char * makebuf(size_t len, int guard_at_end) { @@ -69,7 +76,7 @@ test_stpncpy(const char *s) dst = makebuf(bufsize, j); memset(dst, 'X', bufsize); len = (bufsize < size) ? bufsize : size - 1; - assert(stpncpy(dst, src, bufsize) == dst+len); + assert(stpncpy_fn(dst, src, bufsize) == dst+len); assert(memcmp(src, dst, len) == 0); for (x = len; x < bufsize; x++) assert(dst[x] == '\0'); @@ -78,33 +85,97 @@ test_stpncpy(const char *s) } } -ATF_TC_WITHOUT_HEAD(nul); -ATF_TC_BODY(nul, tc) +static void +test_sentinel(char *dest, char *src, size_t destlen, size_t srclen) { + size_t i; + const char *res, *wantres; + const char *fail = NULL; - test_stpncpy(""); + for (i = 0; i < srclen; i++) + /* src will never include (){} */ + src[i] = '0' + i; + src[srclen] = '\0'; + + /* source sentinels: not to be copied */ + src[-1] = '('; + src[srclen+1] = ')'; + + memset(dest, 0xee, destlen); + + /* destination sentinels: not to be touched */ + dest[-1] = '{'; + dest[destlen] = '}'; + + wantres = dest + (srclen > destlen ? destlen : srclen); + res = stpncpy_fn(dest, src, destlen); + + if (dest[-1] != '{') + fail = "start sentinel overwritten"; + else if (dest[destlen] != '}') + fail = "end sentinel overwritten"; + else if (strncmp(src, dest, destlen) != 0) + fail = "string not copied correctly"; + else if (res != wantres) + fail = "incorrect return value"; + else for (i = srclen; i < destlen; i++) + if (dest[i] != '\0') { + fail = "incomplete NUL padding"; + break; + } + + if (fail) + atf_tc_fail_nonfatal("%s\n" + "stpncpy(%p \"%s\", %p \"%s\", %zu) = %p (want %p)\n", + fail, dest, dest, src, src, destlen, res, wantres); } -ATF_TC_WITHOUT_HEAD(foo); -ATF_TC_BODY(foo, tc) +ATF_TC_WITHOUT_HEAD(null); +ATF_TC_BODY(null, tc) { - - test_stpncpy("foo"); + ATF_CHECK_EQ(stpncpy_fn(NULL, NULL, 0), NULL); } -ATF_TC_WITHOUT_HEAD(glorp); -ATF_TC_BODY(glorp, tc) +ATF_TC_WITHOUT_HEAD(bounds); +ATF_TC_BODY(bounds, tc) { + size_t i; + char buf[64+1]; - test_stpncpy("glorp"); + for (i = 0; i < sizeof(buf) - 1; i++) { + buf[i] = ' ' + i; + buf[i+1] = '\0'; + test_stpncpy(buf); + } +} + +ATF_TC_WITHOUT_HEAD(alignments); +ATF_TC_BODY(alignments, tc) +{ + size_t srcalign, destalign, srclen, destlen; + char src[15+3+64]; /* 15 offsets + 64 max length + NUL + sentinels */ + char dest[15+2+64]; /* 15 offsets + 64 max length + sentinels */ + + for (srcalign = 0; srcalign < 16; srcalign++) + for (destalign = 0; destalign < 16; destalign++) + for (srclen = 0; srclen < 64; srclen++) + for (destlen = 0; destlen < 64; destlen++) + test_sentinel(dest+destalign+1, + src+srcalign+1, destlen, srclen); } ATF_TP_ADD_TCS(tp) { + void *dl_handle; - ATF_TP_ADD_TC(tp, nul); - ATF_TP_ADD_TC(tp, foo); - ATF_TP_ADD_TC(tp, glorp); + dl_handle = dlopen(NULL, RTLD_LAZY); + stpncpy_fn = dlsym(dl_handle, "test_stpncpy"); + if (stpncpy_fn == NULL) + stpncpy_fn = stpncpy; + + ATF_TP_ADD_TC(tp, null); + ATF_TP_ADD_TC(tp, bounds); + ATF_TP_ADD_TC(tp, alignments); return (atf_no_error()); }