From: Arjun Shankar Date: Mon, 13 Oct 2025 13:51:09 +0000 (+0200) Subject: string: Add tests for unique strerror and strsignal strings X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=88ce558a31c041778bd14d177ed700f2f268daea;p=thirdparty%2Fglibc.git 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 --- diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 2c5bf42236..d1ac6409b1 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -716,3 +716,21 @@ tests-static += \ tst-rseq-nptl-static \ # tests-static 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 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 new file mode 100644 index 0000000000..9d9886f138 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-strerror-strings.c @@ -0,0 +1,79 @@ +/* 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 +#include +#define N_(msgid) msgid +const char *const errlist_internal[] __attribute_maybe_unused__ = + { +#define _S(n, str) [ERR_MAP(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 new file mode 100644 index 0000000000..4ba8d5cbcb --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-strerrordesc_np-strings.c @@ -0,0 +1,73 @@ +/* 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 +#include +#define N_(msgid) msgid +const char *const errlist_internal[] __attribute_maybe_unused__ = + { +#define _S(n, str) [ERR_MAP(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 new file mode 100644 index 0000000000..5ce7ea66b9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-xsi-strerror_r-mod.c @@ -0,0 +1,30 @@ +/* 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 +#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"