From fe0a9b0cabda67b359a31f062ebfe577636dc18f Mon Sep 17 00:00:00 2001 From: Patsy Griffin Date: Thu, 11 Dec 2025 22:11:58 -0500 Subject: [PATCH] string: Add tests for unique strerror and strsignal strings (RHEL-109758) Resolves: RHEL-109758 --- glibc-RHEL-109758.patch | 581 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 581 insertions(+) create mode 100644 glibc-RHEL-109758.patch diff --git a/glibc-RHEL-109758.patch b/glibc-RHEL-109758.patch new file mode 100644 index 0000000..6bf25c1 --- /dev/null +++ b/glibc-RHEL-109758.patch @@ -0,0 +1,581 @@ +commit 88ce558a31c041778bd14d177ed700f2f268daea +Author: Arjun Shankar +Date: Mon Oct 13 15:51:09 2025 +0200 + + string: Add tests for unique strerror and strsignal strings + + strerror, strsignal, and their variants should return unique strings for + each known (and, depending on the function, unknown) error/signal. Add + tests to verify this for strerror, strerror_r (GNU and XSI compliant + variants), and strerror_l (for the C locale), strerrordesc_np, + strsignal, sigabbrev_np, and sigdescr_np. + + Co-authored-by: Adhemerval Zanella + Reviewed-by: Florian Weimer + Reviewed-by: Adhemerval Zanella + + Conflicts: + sysdeps/unix/sysv/linux/tst-strerror-strings.c: ERR_MAP is not supported + sysdeps/unix/sysv/linux/tst-strerrordesc_np-strings.c: ERR_MAP is not supported + sysdeps/unix/sysv/linux/tst-xsi-strerror_r-mod.c: add define of _ISOMAC + +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 2c5bf42236..d1ac6409b1 100644 +--- a/sysdeps/unix/sysv/linux/Makefile 2025-12-10 10:36:31.630511707 -0500 ++++ b/sysdeps/unix/sysv/linux/Makefile 2025-12-10 10:40:52.152371031 -0500 +@@ -423,3 +423,21 @@ tests += tst-align-clone tst-getpid1 \ + # __NR_rseq from the internal system call list. + tests-internal += tst-rseq-nptl + endif ++ ++ifeq ($(subdir),string) ++modules-names += \ ++ tst-xsi-strerror_r-mod \ ++ # modules-names ++ ++tests += \ ++ tst-sigabbrev_np-strings \ ++ tst-strerror-strings \ ++ tst-strerror_l-strings \ ++ tst-strerror_r-strings \ ++ tst-strerrordesc_np-strings \ ++ tst-strsignal-strings \ ++ tst-xsi-strerror_r-strings \ ++ # tests ++ ++$(objpfx)tst-xsi-strerror_r-strings: $(objpfx)tst-xsi-strerror_r-mod.so ++endif # $(subdir) == string +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +diff --git a/sysdeps/unix/sysv/linux/tst-sigabbrev_np-strings.c b/sysdeps/unix/sysv/linux/tst-sigabbrev_np-strings.c +new file mode 100644 +index 0000000000..2c0f28c682 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-sigabbrev_np-strings.c +@@ -0,0 +1,61 @@ ++/* Test that sig{abbrev,descr}_np return unique strings for each signal. ++ ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#include "tst-verify-unique-strings.c" ++ ++/* Both functions should return NULL for (unknown) signal numbers outside ++ [1, 31]. */ ++ ++static int ++do_test (void) ++{ ++ char *str_sigabbrev[31]; ++ char *str_sigdescr[31]; ++ ++ for (int i = -128; i <= 128; i++) ++ if (i >= 1 && i <= 31) ++ { ++ str_sigabbrev[i-1] = xstrdup (sigabbrev_np (i)); ++ str_sigdescr[i-1] = xstrdup (sigdescr_np (i)); ++ } ++ else ++ { ++ TEST_VERIFY_EXIT (sigabbrev_np (i) == NULL); ++ TEST_VERIFY_EXIT (sigdescr_np (i) == NULL); ++ } ++ ++ VERIFY_UNIQUE_STRINGS (str_sigabbrev, 31); ++ VERIFY_UNIQUE_STRINGS (str_sigdescr, 31); ++ ++ for (int i = 0; i < 31; i++) ++ { ++ free (str_sigabbrev[i]); ++ free (str_sigdescr[i]); ++ } ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/tst-strerror-strings.c b/sysdeps/unix/sysv/linux/tst-strerror-strings.c +--- a/sysdeps/unix/sysv/linux/tst-strerror-strings.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/sysdeps/unix/sysv/linux/tst-strerror-strings.c 1969-12-31 19:00:00.000000000 -0500 +@@ -0,0 +1,78 @@ ++/* Test that strerror variants return unique strings for each errnum. ++ ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "tst-verify-unique-strings.c" ++ ++/* As defined by stdio-common/errlist-data-gen.c */ ++#include ++#define N_(msgid) msgid ++const char *const errlist_internal[] __attribute_maybe_unused__ = ++ { ++#define _S(n, str) [n] = str, ++#include ++#undef _S ++ }; ++const int errlist_internal_len = array_length (errlist_internal); ++ ++static int ++do_test (void) ++{ ++ char *string[2 * errlist_internal_len + 1]; ++ ++ /* Convenient indexing for error strings from -errlist_internal_len to ++ errlist_internal_len. */ ++ char **err_str = string + errlist_internal_len; ++ ++ unsetenv ("LANGUAGE"); ++ ++ xsetlocale (LC_ALL, "C"); ++ ++ for (int i = -errlist_internal_len; i <= errlist_internal_len; i++) ++ { ++ ++#ifdef TEST_STRERROR_VARIANT ++ /* Used for testing strerror_r and strerror_l. */ ++ err_str[i] = TEST_STRERROR_VARIANT (i); ++#else ++ err_str[i] = xstrdup (strerror (i)); ++#endif ++ ++ int is_unknown_error ++ = (strstr (err_str[i], "Unknown error ") == err_str[i]); ++ TEST_VERIFY_EXIT ((i >= 0 && i < errlist_internal_len) ++ || is_unknown_error); ++ } ++ ++ /* We check for and fail on duplicate strings. */ ++ VERIFY_UNIQUE_STRINGS (string, 2 * errlist_internal_len + 1); ++ ++ for (int i = -errlist_internal_len; i <= errlist_internal_len; i++) ++ free (err_str[i]); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/tst-strerror_l-strings.c b/sysdeps/unix/sysv/linux/tst-strerror_l-strings.c +new file mode 100644 +index 0000000000..65c5a2f08c +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-strerror_l-strings.c +@@ -0,0 +1,40 @@ ++/* Test that strerror_l returns unique strings for each errnum. ++ ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++/* newlocale returns (locale_t) 0 upon error, so it makes for a good initial ++ value that is different from any valid locale_t. */ ++static locale_t loc = (locale_t) 0; ++ ++/* Wrap strerror_l to be plugged into the equivalent strerror test. */ ++static char * ++wrap_strerror_l (int errnum) ++{ ++ if (loc == (locale_t) 0) ++ loc = xnewlocale (LC_ALL_MASK, "C", (locale_t) 0); ++ ++ return xstrdup (strerror_l (errnum, loc)); ++} ++ ++#define TEST_STRERROR_VARIANT wrap_strerror_l ++#include "tst-strerror-strings.c" +diff --git a/sysdeps/unix/sysv/linux/tst-strerror_r-strings.c b/sysdeps/unix/sysv/linux/tst-strerror_r-strings.c +new file mode 100644 +index 0000000000..dea9415eb8 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-strerror_r-strings.c +@@ -0,0 +1,43 @@ ++/* Test that GNU strerror_r returns unique strings for each errnum. ++ ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++/* Wrap strerror_r into a checked variant that can be plugged into the ++ equivalent strerror test. */ ++static char * ++test_and_return_strerror_r (int errnum) ++{ ++ char buf[1024]; ++ ++ char *ret = strerror_r (errnum, buf, sizeof (buf)); ++ ++ /* User supplied buffer used for and only for "Unknown error" strings. */ ++ if (strstr (ret, "Unknown error ") == ret) ++ TEST_VERIFY_EXIT (ret == buf); ++ else ++ TEST_VERIFY_EXIT (ret != buf); ++ ++ return xstrdup (ret); ++} ++ ++#define TEST_STRERROR_VARIANT test_and_return_strerror_r ++#include "tst-strerror-strings.c" +diff --git a/sysdeps/unix/sysv/linux/tst-strerrordesc_np-strings.c b/sysdeps/unix/sysv/linux/tst-strerrordesc_np-strings.c +--- a/sysdeps/unix/sysv/linux/tst-strerrordesc_np-strings.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/sysdeps/unix/sysv/linux/tst-strerrordesc_np-strings.c 1969-12-31 19:00:00.000000000 -0500 +@@ -0,0 +1,72 @@ ++/* Test that strerrordesc_np returns unique strings for each errnum. ++ ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "tst-verify-unique-strings.c" ++ ++/* As defined by stdio-common/errlist-data-gen.c */ ++#include ++#define N_(msgid) msgid ++const char *const errlist_internal[] __attribute_maybe_unused__ = ++ { ++#define _S(n, str) [n] = str, ++#include ++#undef _S ++ }; ++const int errlist_internal_len = array_length (errlist_internal); ++ ++static int ++do_test (void) ++{ ++ char *string[2 * errlist_internal_len + 1]; ++ ++ int i, s; ++ for (i = -errlist_internal_len, s = 0; i <= errlist_internal_len; i++) ++ { ++ const char *ret = strerrordesc_np (i); ++ ++ /* Range of known errors. Some errnums could still be unused. */ ++ if (i >= 0 && i < errlist_internal_len) ++ { ++ if (ret != NULL) ++ { ++ TEST_VERIFY_EXIT (strcasestr (ret, "Unknown error") == NULL); ++ string[s++] = xstrdup (ret); ++ } ++ } ++ else ++ TEST_VERIFY_EXIT (ret == NULL); ++ } ++ ++ /* We check for and fail on duplicate strings. */ ++ VERIFY_UNIQUE_STRINGS (string, s); ++ ++ for (int i = 0; i < s; i++) ++ free (string[i]); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/tst-strsignal-strings.c b/sysdeps/unix/sysv/linux/tst-strsignal-strings.c +new file mode 100644 +index 0000000000..476437aaa4 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-strsignal-strings.c +@@ -0,0 +1,73 @@ ++/* Test that strsignal returns unique strings for each signal. ++ ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "tst-verify-unique-strings.c" ++ ++#define NSTRINGS 257 ++ ++static int ++do_test (void) ++{ ++ char *string[NSTRINGS]; ++ /* Convenient indexing for signal strings from -128 to 128. */ ++ char **sig_str = string + 128; ++ ++ unsetenv ("LANGUAGE"); ++ ++ xsetlocale (LC_ALL, "C"); ++ ++ for (int i = -128; i <= 128; i++) ++ { ++ sig_str[i] = xstrdup (strsignal (i)); ++ ++ if (i > 0 && i <= 31) ++ { ++ /* Signals between 1 and 31 are known. */ ++ TEST_VERIFY_EXIT (strstr (sig_str[i], "Unknown signal ") ++ == NULL); ++ TEST_VERIFY_EXIT (strstr (sig_str[i], "Real-time signal ") ++ == NULL); ++ } ++ else if ((i <= 0) ++ || (i > 31 && i < SIGRTMIN) ++ || (i > SIGRTMAX)) ++ TEST_VERIFY_EXIT (strstr (sig_str[i], "Unknown signal ") ++ == sig_str[i]); ++ ++ else if (i >= SIGRTMIN && i <= SIGRTMAX) ++ TEST_VERIFY_EXIT (strstr (sig_str[i], "Real-time signal ") ++ == sig_str[i]); ++ } ++ ++ VERIFY_UNIQUE_STRINGS (string, NSTRINGS); ++ ++ for (int i = -128; i <= 128; i++) ++ free (sig_str[i]); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/tst-verify-unique-strings.c b/sysdeps/unix/sysv/linux/tst-verify-unique-strings.c +new file mode 100644 +index 0000000000..75a2bc38ff +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-verify-unique-strings.c +@@ -0,0 +1,40 @@ ++/* Test that an array of strings does not contain duplicates. ++ ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++compare_strings (const void *a, const void *b) ++{ ++ const char *stra = * (const char **) a; ++ const char *strb = * (const char **) b; ++ ++ int ret = strcmp (stra, strb); ++ ++ if (!ret) ++ FAIL_EXIT1 ("Found duplicate strings: \"%s\"\n", stra); ++ ++ return ret; ++} ++ ++/* We check for and fail on duplicate strings in the comparator. */ ++#define VERIFY_UNIQUE_STRINGS(strarray, narray) \ ++ qsort ((strarray), (narray), sizeof (char *), compare_strings) +diff --git a/sysdeps/unix/sysv/linux/tst-xsi-strerror_r-mod.c b/sysdeps/unix/sysv/linux/tst-xsi-strerror_r-mod.c +--- a/sysdeps/unix/sysv/linux/tst-xsi-strerror_r-mod.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/sysdeps/unix/sysv/linux/tst-xsi-strerror_r-mod.c 1969-12-31 19:00:00.000000000 -0500 +@@ -0,0 +1,31 @@ ++/* A module that provides XSI compliant strerror_r for testing. ++ ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* This allows us to compile the rest of the test with GNU extensions. */ ++ ++#undef _GNU_SOURCE ++#define _DEFAULT_SOURCE ++#define _ISOMAC ++#include ++ ++int ++xsi_strerror_r (int errnum, char *buf, size_t buflen) ++{ ++ return strerror_r (errnum, buf, buflen); ++} +diff --git a/sysdeps/unix/sysv/linux/tst-xsi-strerror_r-strings.c b/sysdeps/unix/sysv/linux/tst-xsi-strerror_r-strings.c +new file mode 100644 +index 0000000000..49f05c1c0a +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-xsi-strerror_r-strings.c +@@ -0,0 +1,46 @@ ++/* Test that XSI strerror_r returns unique strings for each errnum. ++ ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++extern int ++xsi_strerror_r (int errnum, char *buf, size_t buflen); ++ ++/* Wrap strerror_r into a checked variant that can be plugged into the ++ equivalent strerror test. */ ++static char * ++test_and_return_xsi_strerror_r (int errnum) ++{ ++ char buf[1024]; ++ ++ int ret = xsi_strerror_r (errnum, buf, sizeof (buf)); ++ ++ /* Unknown errnums lead to a positive error returned from strerror_r. */ ++ if (strstr (buf, "Unknown error ") == buf) ++ TEST_VERIFY (ret > 0); ++ else ++ TEST_VERIFY (ret == 0); ++ ++ return xstrdup (buf); ++} ++ ++#define TEST_STRERROR_VARIANT test_and_return_xsi_strerror_r ++#include "tst-strerror-strings.c"