aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2024-06-27 16:26:56 +0200
committerAndreas K. Hüttel <dilfridge@gentoo.org>2024-08-09 22:46:21 +0200
commitb2e3445d1af4e8fc69c31dc9e76ac8027d1bc37e (patch)
treec58d5da7bc0bba7faae1d252518ca69a89ef1309
parentEnhance test coverage for strnlen, wcsnlen (diff)
downloadglibc-b2e3445d1af4e8fc69c31dc9e76ac8027d1bc37e.tar.gz
glibc-b2e3445d1af4e8fc69c31dc9e76ac8027d1bc37e.tar.bz2
glibc-b2e3445d1af4e8fc69c31dc9e76ac8027d1bc37e.zip
Enhanced test coverage for strncmp, wcsncmp
Add string/test-strncmp-nonarray and wcsmbs/test-wcsncmp-nonarray. This is the test that uncovered bug 31934. Test run time is more than one minute on a fairly current system, so turn these into xtests that do not run automatically. Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com> (cherry picked from commit 54252394c25ddf0062e288d4a6ab7a885f8ae009) (cherry picked from commit 46f19b234244f4654b9e3898ac1c27de86068222)
-rw-r--r--string/Makefile5
-rw-r--r--string/test-Xncmp-nonarray.c183
-rw-r--r--string/test-strncmp-nonarray.c4
-rw-r--r--wcsmbs/Makefile4
-rw-r--r--wcsmbs/test-wcsncmp-nonarray.c5
5 files changed, 200 insertions, 1 deletions
diff --git a/string/Makefile b/string/Makefile
index 2e20fc00fd..1dff405c27 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -236,7 +236,10 @@ tests-unsupported += $(tests-translation)
endif
# This test allocates a lot of memory and can run for a long time.
-xtests = tst-strcoll-overflow
+xtests += tst-strcoll-overflow
+
+# This test runs for a long time.
+xtests += test-strncmp-nonarray
# This test needs libdl.
ifeq (yes,$(build-shared))
diff --git a/string/test-Xncmp-nonarray.c b/string/test-Xncmp-nonarray.c
new file mode 100644
index 0000000000..9f3a3ca75d
--- /dev/null
+++ b/string/test-Xncmp-nonarray.c
@@ -0,0 +1,183 @@
+/* Test non-array inputs to string comparison functions.
+ Copyright (C) 2024 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 skeleton file is included from string/test-strncmp-nonarray.c and
+ wcsmbs/test-wcsncmp-nonarray.c to test that reading of the arrays stops
+ at the first null character.
+
+ TEST_IDENTIFIER must be the test function identifier. TEST_NAME is
+ the same as a string.
+
+ CHAR must be defined as the character type. */
+
+#include <array_length.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/next_to_fault.h>
+#include <support/test-driver.h>
+#include <sys/param.h>
+#include <unistd.h>
+
+/* Much shorter than test-Xnlen-nonarray.c because of deeply nested loops. */
+enum { buffer_length = 80 };
+
+/* The test buffer layout follows what is described test-Xnlen-nonarray.c,
+ except that there two buffers, left and right. The variables
+ a_count, zero_count, start_offset are all duplicated. */
+
+/* Return the maximum string length for a string that starts at
+ start_offset. */
+static int
+string_length (int a_count, int start_offset)
+{
+ if (start_offset == buffer_length || start_offset >= a_count)
+ return 0;
+ else
+ return a_count - start_offset;
+}
+
+/* This is the valid maximum length argument computation for
+ strnlen/wcsnlen. See text-Xnlen-nonarray.c. */
+static int
+maximum_length (int start_offset, int zero_count)
+{
+ if (start_offset == buffer_length)
+ return 0;
+ else if (zero_count > 0)
+ /* Effectively unbounded, but we need to stop fairly low,
+ otherwise testing takes too long. */
+ return buffer_length + 32;
+ else
+ return buffer_length - start_offset;
+}
+
+typedef __typeof (TEST_IDENTIFIER) *proto_t;
+
+#define TEST_MAIN
+#include "test-string.h"
+
+IMPL (TEST_IDENTIFIER, 1)
+
+static int
+test_main (void)
+{
+ TEST_VERIFY_EXIT (sysconf (_SC_PAGESIZE) >= buffer_length);
+ test_init ();
+
+ struct support_next_to_fault left_ntf
+ = support_next_to_fault_allocate (buffer_length * sizeof (CHAR));
+ CHAR *left_buffer = (CHAR *) left_ntf.buffer;
+ struct support_next_to_fault right_ntf
+ = support_next_to_fault_allocate (buffer_length * sizeof (CHAR));
+ CHAR *right_buffer = (CHAR *) right_ntf.buffer;
+
+ FOR_EACH_IMPL (impl, 0)
+ {
+ printf ("info: testing %s\n", impl->name);
+ for (size_t i = 0; i < buffer_length; ++i)
+ left_buffer[i] = 'A';
+
+ for (int left_zero_count = 0; left_zero_count <= buffer_length;
+ ++left_zero_count)
+ {
+ if (left_zero_count > 0)
+ left_buffer[buffer_length - left_zero_count] = 0;
+ int left_a_count = buffer_length - left_zero_count;
+ for (size_t i = 0; i < buffer_length; ++i)
+ right_buffer[i] = 'A';
+ for (int right_zero_count = 0; right_zero_count <= buffer_length;
+ ++right_zero_count)
+ {
+ if (right_zero_count > 0)
+ right_buffer[buffer_length - right_zero_count] = 0;
+ int right_a_count = buffer_length - right_zero_count;
+ for (int left_start_offset = 0;
+ left_start_offset <= buffer_length;
+ ++left_start_offset)
+ {
+ CHAR *left_start_pointer = left_buffer + left_start_offset;
+ int left_maxlen
+ = maximum_length (left_start_offset, left_zero_count);
+ int left_length
+ = string_length (left_a_count, left_start_offset);
+ for (int right_start_offset = 0;
+ right_start_offset <= buffer_length;
+ ++right_start_offset)
+ {
+ CHAR *right_start_pointer
+ = right_buffer + right_start_offset;
+ int right_maxlen
+ = maximum_length (right_start_offset, right_zero_count);
+ int right_length
+ = string_length (right_a_count, right_start_offset);
+
+ /* Maximum length is modelled after strnlen/wcsnlen,
+ and must be valid for both pointer arguments at
+ the same time. */
+ int maxlen = MIN (left_maxlen, right_maxlen);
+
+ for (int length_argument = 0; length_argument <= maxlen;
+ ++length_argument)
+ {
+ if (test_verbose)
+ {
+ printf ("left: zero_count=%d"
+ " a_count=%d start_offset=%d\n",
+ left_zero_count, left_a_count,
+ left_start_offset);
+ printf ("right: zero_count=%d"
+ " a_count=%d start_offset=%d\n",
+ right_zero_count, right_a_count,
+ right_start_offset);
+ printf ("length argument: %d\n",
+ length_argument);
+ }
+
+ /* Effective lengths bounded by length argument.
+ The effective length determines the
+ outcome of the comparison. */
+ int left_effective
+ = MIN (left_length, length_argument);
+ int right_effective
+ = MIN (right_length, length_argument);
+ if (left_effective == right_effective)
+ TEST_COMPARE (CALL (impl,
+ left_start_pointer,
+ right_start_pointer,
+ length_argument), 0);
+ else if (left_effective < right_effective)
+ TEST_COMPARE (CALL (impl,
+ left_start_pointer,
+ right_start_pointer,
+ length_argument) < 0, 1);
+ else
+ TEST_COMPARE (CALL (impl,
+ left_start_pointer,
+ right_start_pointer,
+ length_argument) > 0, 1);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/string/test-strncmp-nonarray.c b/string/test-strncmp-nonarray.c
new file mode 100644
index 0000000000..581e52d01b
--- /dev/null
+++ b/string/test-strncmp-nonarray.c
@@ -0,0 +1,4 @@
+#define TEST_IDENTIFIER strncmp
+#define TEST_NAME "strncmp"
+typedef char CHAR;
+#include "test-Xncmp-nonarray.c"
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
index c51c9b4f1f..63adf0e8ef 100644
--- a/wcsmbs/Makefile
+++ b/wcsmbs/Makefile
@@ -206,6 +206,10 @@ tests := \
wcsmbs-tst1 \
# tests
+# This test runs for a long time.
+xtests += test-wcsncmp-nonarray
+
+
include ../Rules
ifeq ($(run-built-tests),yes)
diff --git a/wcsmbs/test-wcsncmp-nonarray.c b/wcsmbs/test-wcsncmp-nonarray.c
new file mode 100644
index 0000000000..1ad9ebd8fd
--- /dev/null
+++ b/wcsmbs/test-wcsncmp-nonarray.c
@@ -0,0 +1,5 @@
+#include <wchar.h>
+#define TEST_IDENTIFIER wcsncmp
+#define TEST_NAME "wcsncmp"
+typedef wchar_t CHAR;
+#include "../string/test-Xncmp-nonarray.c"