Lasse Collin wrote: > As mentioned earlier, Clang doesn't optimize if it sees the nonnull > attribute only in a function declaration. A discussion from 2017[1] > gives an impression that glibc's headers might have been a reason for > this. > > [1] > https://discourse.llvm.org/t/rfc-do-not-optimize-on-basis-of-attribute-nonnull-in-glibc-headers/43547
Well, now it does. With clang 22 + UBSAN I see these test failures: FAIL: test-memchr ================= test-memchr.c:50:19: runtime error: null pointer passed as argument 1, which is declared to never be null /usr/include/string.h:119:34: note: nonnull attribute specified here SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior test-memchr.c:50:19 FAIL test-memchr (exit status: 1) FAIL: test-memcmp ================= test-memcmp.c:48:18: runtime error: null pointer passed as argument 1, which is declared to never be null /usr/include/string.h:76:33: note: nonnull attribute specified here SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior test-memcmp.c:48:18 FAIL test-memcmp (exit status: 1) and so on. Since I now have a clang 22 + UBSAN + ASAN pass in my CI, there is need to silence these failures. Previously I had used gnulib-tool options --avoid=memchr-tests --avoid=memcmp-tests ... but this is no longer practical. 2026-08-16 Bruno Haible <[email protected]> tests: Avoid some test failures with the clang UBSAN. * tests/test-bsearch.c (main): Disable the N3322 test on glibc systems. * tests/test-memccpy.c (main): Likewise. * tests/test-memchr.c (main): Likewise. * tests/test-memcmp.c (main): Likewise. * tests/test-memcpy.c (main): Likewise. * tests/test-memmove.c (main): Likewise. * tests/test-memset.c (main): Likewise. * tests/test-memset_explicit.c (main): Likewise. * tests/test-qsort.c (main): Likewise. * tests/test-strncat.c (main): Likewise. * tests/test-strncmp.c (main): Likewise. * tests/test-strncpy.c (main): Likewise. * tests/test-strndup.c (main): Likewise. * tests/test-wcsncat.c (main): Likewise. * tests/test-wcsncmp.c (main): Likewise. * tests/test-wcsncpy.c (main): Likewise.
From dbdd898e9e63524df43421b95c1cb3cc548db40d Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Mon, 17 Aug 2026 00:27:42 +0200 Subject: [PATCH] tests: Avoid some test failures with the clang UBSAN. * tests/test-bsearch.c (main): Disable the N3322 test on glibc systems. * tests/test-memccpy.c (main): Likewise. * tests/test-memchr.c (main): Likewise. * tests/test-memcmp.c (main): Likewise. * tests/test-memcpy.c (main): Likewise. * tests/test-memmove.c (main): Likewise. * tests/test-memset.c (main): Likewise. * tests/test-memset_explicit.c (main): Likewise. * tests/test-qsort.c (main): Likewise. * tests/test-strncat.c (main): Likewise. * tests/test-strncmp.c (main): Likewise. * tests/test-strncpy.c (main): Likewise. * tests/test-strndup.c (main): Likewise. * tests/test-wcsncat.c (main): Likewise. * tests/test-wcsncmp.c (main): Likewise. * tests/test-wcsncpy.c (main): Likewise. --- ChangeLog | 20 ++++++++++++++++++++ tests/test-bsearch.c | 2 ++ tests/test-memccpy.c | 2 ++ tests/test-memchr.c | 3 +++ tests/test-memcmp.c | 3 +++ tests/test-memcpy.c | 3 +++ tests/test-memmove.c | 3 +++ tests/test-memset.c | 3 +++ tests/test-memset_explicit.c | 2 ++ tests/test-qsort.c | 2 ++ tests/test-strncat.c | 7 +++++-- tests/test-strncmp.c | 3 +++ tests/test-strncpy.c | 3 +++ tests/test-strndup.c | 3 +++ tests/test-wcsncat.c | 6 ++++-- tests/test-wcsncmp.c | 2 ++ tests/test-wcsncpy.c | 2 ++ 17 files changed, 65 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 32a9a08db7..0342ca9cac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2026-08-16 Bruno Haible <[email protected]> + + tests: Avoid some test failures with the clang UBSAN. + * tests/test-bsearch.c (main): Disable the N3322 test on glibc systems. + * tests/test-memccpy.c (main): Likewise. + * tests/test-memchr.c (main): Likewise. + * tests/test-memcmp.c (main): Likewise. + * tests/test-memcpy.c (main): Likewise. + * tests/test-memmove.c (main): Likewise. + * tests/test-memset.c (main): Likewise. + * tests/test-memset_explicit.c (main): Likewise. + * tests/test-qsort.c (main): Likewise. + * tests/test-strncat.c (main): Likewise. + * tests/test-strncmp.c (main): Likewise. + * tests/test-strncpy.c (main): Likewise. + * tests/test-strndup.c (main): Likewise. + * tests/test-wcsncat.c (main): Likewise. + * tests/test-wcsncmp.c (main): Likewise. + * tests/test-wcsncpy.c (main): Likewise. + 2026-08-16 Bruno Haible <[email protected]> doc: Mention a wcsncat bug. diff --git a/tests/test-bsearch.c b/tests/test-bsearch.c index 9cfdcfe3cb..60cd0ff08c 100644 --- a/tests/test-bsearch.c +++ b/tests/test-bsearch.c @@ -64,9 +64,11 @@ main (void) { /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (bsearch ("x", NULL, 0, 1, cmp) == NULL); ASSERT (volatile_null_bsearch ("x", NULL, 0, 1, cmp) == NULL); +#endif return test_exit_status; } diff --git a/tests/test-memccpy.c b/tests/test-memccpy.c index 6f9e6d9c34..c942e18675 100644 --- a/tests/test-memccpy.c +++ b/tests/test-memccpy.c @@ -56,6 +56,7 @@ main (void) /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (memccpy (NULL, "x", '?', 0) == NULL); { @@ -64,6 +65,7 @@ main (void) } ASSERT (volatile_null_memccpy (NULL, "x", '?', 0) == NULL); +#endif return test_exit_status; } diff --git a/tests/test-memchr.c b/tests/test-memchr.c index c125244a99..ea662ca2f2 100644 --- a/tests/test-memchr.c +++ b/tests/test-memchr.c @@ -152,9 +152,12 @@ main (void) /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ + && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (memchr (NULL, '?', 0) == NULL); ASSERT (volatile_null_memchr (NULL, '?', 0) == NULL); +#endif return test_exit_status; } diff --git a/tests/test-memcmp.c b/tests/test-memcmp.c index be68403159..601f46859f 100644 --- a/tests/test-memcmp.c +++ b/tests/test-memcmp.c @@ -98,11 +98,14 @@ main (void) /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ + && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (memcmp (NULL, "x", 0) == 0); ASSERT (memcmp ("x", NULL, 0) == 0); ASSERT (memcmp (NULL, NULL, 0) == 0); ASSERT (volatile_null_memcmp (NULL, "x", 0) == 0); +#endif return test_exit_status; } diff --git a/tests/test-memcpy.c b/tests/test-memcpy.c index 8d0fdfb88d..8836e9680a 100644 --- a/tests/test-memcpy.c +++ b/tests/test-memcpy.c @@ -56,6 +56,8 @@ main (void) /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ + && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (memcpy (NULL, "x", 0) == NULL); { @@ -66,6 +68,7 @@ main (void) /* Redirect via the volatile function pointer to ensure that that the ASSERT in null_memcpy won't be optimized away by GCC 6.3.0. */ ASSERT (volatile_null_memcpy (NULL, "x", 0) == NULL); +#endif return test_exit_status; } diff --git a/tests/test-memmove.c b/tests/test-memmove.c index 8709e9082f..6b433ce7f0 100644 --- a/tests/test-memmove.c +++ b/tests/test-memmove.c @@ -56,6 +56,8 @@ main (void) /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ + && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (memmove (NULL, "x", 0) == NULL); { @@ -64,6 +66,7 @@ main (void) } ASSERT (volatile_null_memmove (NULL, "x", 0) == NULL); +#endif return test_exit_status; } diff --git a/tests/test-memset.c b/tests/test-memset.c index 258d62754c..39dd047b65 100644 --- a/tests/test-memset.c +++ b/tests/test-memset.c @@ -55,9 +55,12 @@ main (void) { /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ + && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (memset (NULL, '?', 0) == NULL); ASSERT (volatile_null_memset (NULL, '?', 0) == NULL); +#endif return test_exit_status; } diff --git a/tests/test-memset_explicit.c b/tests/test-memset_explicit.c index 79f42a38c8..e2ab32097f 100644 --- a/tests/test-memset_explicit.c +++ b/tests/test-memset_explicit.c @@ -280,9 +280,11 @@ main () /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (memset_explicit (NULL, '?', 0) == NULL); ASSERT (volatile_null_memset_explicit (NULL, '?', 0) == NULL); +#endif return test_exit_status; } diff --git a/tests/test-qsort.c b/tests/test-qsort.c index 9efbe53397..8904882ac1 100644 --- a/tests/test-qsort.c +++ b/tests/test-qsort.c @@ -61,9 +61,11 @@ main (void) /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) qsort (NULL, 0, 1, cmp); volatile_null_qsort (NULL, 0, 1, cmp); +#endif return 0; } diff --git a/tests/test-strncat.c b/tests/test-strncat.c index 2eeb46d77c..162b3d4e42 100644 --- a/tests/test-strncat.c +++ b/tests/test-strncat.c @@ -89,9 +89,11 @@ main () /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ -#if 0 /* I think this is invalid, per ISO C 23 § 7.26.3.2. */ +#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ + && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) +# if 0 /* I think this is invalid, per ISO C 23 § 7.26.3.2. */ ASSERT (strncat (NULL, "x", 0) == NULL); -#endif +# endif { char y[2] = { 'x', '\0' }; @@ -99,6 +101,7 @@ main () ASSERT (volatile_null_strncat (y, NULL, 0) == y); } +#endif return test_exit_status; } diff --git a/tests/test-strncmp.c b/tests/test-strncmp.c index 95ff26085a..cbc2327861 100644 --- a/tests/test-strncmp.c +++ b/tests/test-strncmp.c @@ -57,11 +57,14 @@ main (void) { /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ + && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (strncmp (NULL, "x", 0) == 0); ASSERT (strncmp ("x", NULL, 0) == 0); ASSERT (strncmp (NULL, NULL, 0) == 0); ASSERT (volatile_null_strncmp (NULL, "x", 0) == 0); +#endif return test_exit_status; } diff --git a/tests/test-strncpy.c b/tests/test-strncpy.c index 80b79f4e0c..2bbbecd991 100644 --- a/tests/test-strncpy.c +++ b/tests/test-strncpy.c @@ -127,6 +127,8 @@ main (void) /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ + && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (strncpy (NULL, "x", 0) == NULL); { @@ -135,6 +137,7 @@ main (void) ASSERT (volatile_null_strncpy (y, NULL, 0) == y); } +#endif return test_exit_status; } diff --git a/tests/test-strndup.c b/tests/test-strndup.c index 84c94184b6..b7f9db05c5 100644 --- a/tests/test-strndup.c +++ b/tests/test-strndup.c @@ -55,9 +55,12 @@ main (void) { /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ + && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (strndup (NULL, 0) != NULL); ASSERT (volatile_null_strndup (NULL, 0) != NULL); +#endif return test_exit_status; } diff --git a/tests/test-wcsncat.c b/tests/test-wcsncat.c index f18f77a300..bf5cc48ae8 100644 --- a/tests/test-wcsncat.c +++ b/tests/test-wcsncat.c @@ -58,9 +58,10 @@ main () /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ -#if 0 /* I think this is invalid, per ISO C 23 § 7.31.4.3.2. */ +#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) +# if 0 /* I think this is invalid, per ISO C 23 § 7.31.4.3.2. */ ASSERT (wcsncat (NULL, L"x", 0) == NULL); -#endif +# endif { wchar_t y[2] = { L'x', 0 }; @@ -68,6 +69,7 @@ main () ASSERT (volatile_null_wcsncat (y, NULL, 0) == y); } +#endif return test_exit_status; } diff --git a/tests/test-wcsncmp.c b/tests/test-wcsncmp.c index 0772925bbc..16990772ad 100644 --- a/tests/test-wcsncmp.c +++ b/tests/test-wcsncmp.c @@ -207,11 +207,13 @@ main (int argc, char *argv[]) /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (wcsncmp (NULL, L"x", 0) == 0); ASSERT (wcsncmp (L"x", NULL, 0) == 0); ASSERT (wcsncmp (NULL, NULL, 0) == 0); ASSERT (volatile_null_wcsncmp (NULL, L"x", 0) == 0); +#endif return test_exit_status; } diff --git a/tests/test-wcsncpy.c b/tests/test-wcsncpy.c index 25bc00c7d9..a2e8622ca8 100644 --- a/tests/test-wcsncpy.c +++ b/tests/test-wcsncpy.c @@ -56,6 +56,7 @@ main (void) /* Test zero-length operations on NULL pointers, allowed by <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ +#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (wcsncpy (NULL, L"x", 0) == NULL); { @@ -64,6 +65,7 @@ main (void) ASSERT (volatile_null_wcsncpy (y, NULL, 0) == y); } +#endif return test_exit_status; } -- 2.53.0
