[PATCH v3] string: Add tests for unique strerror error strings
Arjun Shankar
arjun@redhat.com
Thu Sep 11 13:15:58 GMT 2025
strerror and its variants should return unique strings for each
known/unknown error. Add tests to verify this for strerror, strerror_r
(GNU and XSI compliant variants), and strerror_l (for the C locale).
strerror_r is special in that the GNU variant returns "Unknown error"
strings (and only those) in the user supplied buffer, returning
read-only internal strings for known errors. In contrast, the XSI
compliant variant always uses the user supplied buffer but returns an
error in its integer return value for unknown strings. Additionally test
for these as well.
---
v2: https://inbox.sourceware.org/libc-alpha/20250911110347.525300-1-arjun@redhat.com/
Changes in v3: Added a test for XSI compliant strerror_r variant.
---
sysdeps/unix/sysv/linux/Makefile | 11 +++
.../unix/sysv/linux/tst-strerror-strings.c | 79 +++++++++++++++++++
.../unix/sysv/linux/tst-strerror_l-strings.c | 40 ++++++++++
.../unix/sysv/linux/tst-strerror_r-strings.c | 43 ++++++++++
.../unix/sysv/linux/tst-xsi-strerror_r-mod.c | 30 +++++++
.../sysv/linux/tst-xsi-strerror_r-strings.c | 46 +++++++++++
6 files changed, 249 insertions(+)
create mode 100644 sysdeps/unix/sysv/linux/tst-strerror-strings.c
create mode 100644 sysdeps/unix/sysv/linux/tst-strerror_l-strings.c
create mode 100644 sysdeps/unix/sysv/linux/tst-strerror_r-strings.c
create mode 100644 sysdeps/unix/sysv/linux/tst-xsi-strerror_r-mod.c
create mode 100644 sysdeps/unix/sysv/linux/tst-xsi-strerror_r-strings.c
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 2c5bf42236..a8bfc597df 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -716,3 +716,14 @@ tests-static += \
tst-rseq-nptl-static \
# tests-static
endif
+
+ifeq ($(subdir),string)
+modules-names += tst-xsi-strerror_r-mod
+tests += \
+ tst-strerror-strings \
+ tst-strerror_l-strings \
+ tst-strerror_r-strings \
+ tst-xsi-strerror_r-strings \
+ # tests
+$(objpfx)tst-xsi-strerror_r-strings: $(objpfx)tst-xsi-strerror_r-mod.so
+endif
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..ae9c12f377
--- /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
+ <https://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <support/support.h>
+#include <support/check.h>
+
+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 error strings: \"%s\"\n", stra);
+
+ return ret;
+}
+
+#define NSTRINGS 2049
+
+static int
+do_test (void)
+{
+ char *string[NSTRINGS];
+ /* Convenient indexing for error strings from -1024 to 1024. */
+ char **err_str = string + 1024;
+
+ unsetenv ("LANGUAGE");
+
+ xsetlocale (LC_ALL, "C");
+
+ for (int i = -1024; i <= 1024; 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
+
+ /* Negative as well as large positive errnums are unused. 160 allows
+ us to define more errors without needing to update this test. */
+ int is_unknown_error
+ = (strstr (err_str[i], "Unknown error ") == err_str[i]);
+ TEST_VERIFY_EXIT ((i >= 0 && i < 160) || is_unknown_error);
+ }
+
+ /* We check for and fail on duplicate strings in the comparator. */
+ qsort (string, NSTRINGS, sizeof (char *), compare_strings);
+
+ for (int i = -1024; i <= 1024; i++)
+ free (err_str[i]);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <support/support.h>
+#include <support/check.h>
+
+/* 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <support/support.h>
+#include <support/check.h>
+
+/* 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-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
+ <https://www.gnu.org/licenses/>. */
+
+/* This allows us to compile the rest of the test with GNU extensions. */
+
+#undef _GNU_SOURCE
+#define _DEFAULT_SOURCE
+#include <string.h>
+
+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
+ <https://www.gnu.org/licenses/>. */
+
+#include <string.h>
+#include <support/support.h>
+#include <support/check.h>
+
+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"
--
2.50.1
More information about the Libc-alpha
mailing list