Disable use of -fsignaling-nans if compiler does not support it
[glibc.git] / string / tst-cmp.c
blob1d6bc16b3864edeb5ce447283f1841545841c740
1 /* Alignment/padding coverage test for string comparison.
2 Copyright (C) 2016-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 /* This performs test comparisons with various (mis)alignments and
20 characters in the padding. It is partly a regression test for bug
21 20327. */
23 #include <limits.h>
24 #include <malloc.h>
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <libc-diag.h>
31 static int
32 signum (int val)
34 if (val < 0)
35 return -1;
36 if (val > 0)
37 return 1;
38 else
39 return 0;
42 static size_t
43 max_size_t (size_t left, size_t right)
45 if (left > right)
46 return left;
47 else
48 return right;
51 /* Wrappers for strncmp and strncasecmp which determine the maximum
52 string length in some, either based on the input string length, or
53 using fixed constants. */
55 static int
56 strncmp_no_terminator (const char *left, const char *right)
58 size_t left_len = strlen (left);
59 size_t right_len = strlen (right);
60 return strncmp (left, right, max_size_t (left_len, right_len));
63 static int
64 strncasecmp_no_terminator (const char *left, const char *right)
66 size_t left_len = strlen (left);
67 size_t right_len = strlen (right);
68 return strncasecmp (left, right, max_size_t (left_len, right_len));
71 static int
72 strncmp_terminator (const char *left, const char *right)
74 size_t left_len = strlen (left);
75 size_t right_len = strlen (right);
76 return strncmp (left, right, max_size_t (left_len, right_len));
79 static int
80 strncasecmp_terminator (const char *left, const char *right)
82 size_t left_len = strlen (left);
83 size_t right_len = strlen (right);
84 return strncasecmp (left, right, max_size_t (left_len, right_len));
87 static int
88 strncmp_64 (const char *left, const char *right)
90 return strncmp (left, right, 64);
93 static int
94 strncasecmp_64 (const char *left, const char *right)
96 return strncasecmp (left, right, 64);
99 static int
100 strncmp_max (const char *left, const char *right)
102 DIAG_PUSH_NEEDS_COMMENT;
103 #if __GNUC_PREREQ (7, 0)
104 /* GCC 9 warns about the size passed to strncmp being larger than
105 PTRDIFF_MAX; the use of SIZE_MAX is deliberate here. */
106 DIAG_IGNORE_NEEDS_COMMENT (9, "-Wstringop-overflow=");
107 #endif
108 #if __GNUC_PREREQ (11, 0)
109 /* Likewise GCC 11, with a different warning option. */
110 DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overread");
111 #endif
112 return strncmp (left, right, SIZE_MAX);
113 DIAG_POP_NEEDS_COMMENT;
116 static int
117 strncasecmp_max (const char *left, const char *right)
119 DIAG_PUSH_NEEDS_COMMENT;
120 #if __GNUC_PREREQ (7, 0)
121 /* GCC 9 warns about the size passed to strncasecmp being larger
122 than PTRDIFF_MAX; the use of SIZE_MAX is deliberate here. */
123 DIAG_IGNORE_NEEDS_COMMENT (9, "-Wstringop-overflow=");
124 #endif
125 #if __GNUC_PREREQ (11, 0)
126 /* Likewise GCC 11, with a different warning option. */
127 DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overread");
128 #endif
129 return strncasecmp (left, right, SIZE_MAX);
130 DIAG_POP_NEEDS_COMMENT;
134 do_test (void)
136 enum {
137 max_align = 64,
138 max_string_length = 33
140 size_t blob_size = max_align + max_string_length + 1;
141 char *left = memalign (max_align, blob_size);
142 char *right = memalign (max_align, blob_size);
143 if (left == NULL || right == NULL)
145 printf ("error: out of memory\n");
146 return 1;
149 const struct
151 const char *name;
152 int (*implementation) (const char *, const char *);
153 } functions[] =
155 { "strcmp", strcmp },
156 { "strcasecmp", strcasecmp },
157 { "strncmp (without NUL)", strncmp_no_terminator},
158 { "strncasecmp (without NUL)", strncasecmp_no_terminator},
159 { "strncmp (with NUL)", strncmp_terminator},
160 { "strncasecmp (with NUL)", strncasecmp_terminator},
161 { "strncmp (length 64)", strncmp_64},
162 { "strncasecmp (length 64)", strncasecmp_64},
163 { "strncmp (length SIZE_MAX)", strncmp_max},
164 { "strncasecmp (length SIZE_MAX)", strncasecmp_max},
165 { NULL, NULL }
167 const char *const strings[] =
170 "0",
171 "01",
172 "01234567",
173 "0123456789abcde",
174 "0123456789abcdef",
175 "0123456789abcdefg",
176 "1",
177 "10",
178 "123456789abcdef",
179 "123456789abcdefg",
180 "23456789abcdef",
181 "23456789abcdefg",
182 "abcdefghijklmnopqrstuvwxyzABCDEF",
183 NULL
185 const unsigned char pads[] =
186 { 0, 1, 32, 64, 128, '0', '1', 'e', 'f', 'g', 127, 192, 255 };
188 bool errors = false;
189 for (int left_idx = 0; strings[left_idx] != NULL; ++left_idx)
190 for (int left_align = 0; left_align < max_align; ++left_align)
191 for (unsigned pad_left = 0; pad_left < sizeof (pads); ++pad_left)
193 memset (left, pads[pad_left], blob_size);
194 strcpy (left + left_align, strings[left_idx]);
196 for (int right_idx = 0; strings[right_idx] != NULL; ++right_idx)
197 for (unsigned pad_right = 0; pad_right < sizeof (pads);
198 ++pad_right)
199 for (int right_align = 0; right_align < max_align;
200 ++right_align)
202 memset (right, pads[pad_right], blob_size);
203 strcpy (right + right_align, strings[right_idx]);
205 for (int func = 0; functions[func].name != NULL; ++func)
207 int expected = left_idx - right_idx;
208 int actual = functions[func].implementation
209 (left + left_align, right + right_align);
210 if (signum (actual) != signum (expected))
212 printf ("error: mismatch for %s: %d\n"
213 " left: \"%s\"\n"
214 " right: \"%s\"\n"
215 " pad_left = %u, pad_right = %u,\n"
216 " left_align = %d, right_align = %d\n",
217 functions[func].name, actual,
218 strings[left_idx], strings[right_idx],
219 pad_left, pad_right,
220 left_align, right_align);
221 errors = true;
226 free (right);
227 free (left);
228 return errors;
231 /* The nested loops need a long time to complete on slower
232 machines. */
233 #define TIMEOUT 600
235 #include <support/test-driver.c>