]> git.ipfire.org Git - thirdparty/glibc.git/blob - string/test-strncasecmp.c
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / string / test-strncasecmp.c
1 /* Test and measure strncasecmp functions.
2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Written by Jakub Jelinek <jakub@redhat.com>, 1999.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
19
20 #include <locale.h>
21 #include <ctype.h>
22 #define TEST_MAIN
23 #define TEST_NAME "strncasecmp"
24 #include "test-string.h"
25
26 typedef int (*proto_t) (const char *, const char *, size_t);
27 static int simple_strncasecmp (const char *, const char *, size_t);
28 static int stupid_strncasecmp (const char *, const char *, size_t);
29
30 IMPL (stupid_strncasecmp, 0)
31 IMPL (simple_strncasecmp, 0)
32 IMPL (strncasecmp, 1)
33
34 static int
35 simple_strncasecmp (const char *s1, const char *s2, size_t n)
36 {
37 int ret;
38
39 if (n == 0)
40 return 0;
41
42 while ((ret = ((unsigned char) tolower (*s1)
43 - (unsigned char) tolower (*s2))) == 0
44 && *s1++)
45 {
46 if (--n == 0)
47 return 0;
48 ++s2;
49 }
50 return ret;
51 }
52
53 static int
54 stupid_strncasecmp (const char *s1, const char *s2, size_t max)
55 {
56 size_t ns1 = strlen (s1) + 1;
57 size_t ns2 = strlen (s2) + 1;
58 size_t n = ns1 < ns2 ? ns1 : ns2;
59 if (n > max)
60 n = max;
61 int ret = 0;
62
63 while (n--)
64 {
65 if ((ret = ((unsigned char) tolower (*s1)
66 - (unsigned char) tolower (*s2))) != 0)
67 break;
68 ++s1;
69 ++s2;
70 }
71 return ret;
72 }
73
74 static int
75 check_result (impl_t *impl, const char *s1, const char *s2, size_t n,
76 int exp_result)
77 {
78 int result = CALL (impl, s1, s2, n);
79 if ((exp_result == 0 && result != 0)
80 || (exp_result < 0 && result >= 0)
81 || (exp_result > 0 && result <= 0))
82 {
83 error (0, 0, "Wrong result in function %s %d %d", impl->name,
84 result, exp_result);
85 ret = 1;
86 return -1;
87 }
88
89 return 0;
90 }
91
92 static void
93 do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n,
94 int exp_result)
95 {
96 if (check_result (impl, s1, s2, n, exp_result) < 0)
97 return;
98 }
99
100 static void
101 do_test (size_t align1, size_t align2, size_t n, size_t len, int max_char,
102 int exp_result)
103 {
104 size_t i;
105 char *s1, *s2;
106
107 if (len == 0)
108 return;
109
110 align1 &= 7;
111 if (align1 + len + 1 >= page_size)
112 return;
113
114 align2 &= 7;
115 if (align2 + len + 1 >= page_size)
116 return;
117
118 s1 = (char *) (buf1 + align1);
119 s2 = (char *) (buf2 + align2);
120
121 for (i = 0; i < len; i++)
122 {
123 s1[i] = toupper (1 + 23 * i % max_char);
124 s2[i] = tolower (s1[i]);
125 }
126
127 s1[len] = s2[len] = 0;
128 s1[len + 1] = 23;
129 s2[len + 1] = 24 + exp_result;
130 if ((s2[len - 1] == 'z' && exp_result == -1)
131 || (s2[len - 1] == 'a' && exp_result == 1))
132 s1[len - 1] += exp_result;
133 else
134 s2[len - 1] -= exp_result;
135
136 FOR_EACH_IMPL (impl, 0)
137 do_one_test (impl, s1, s2, n, exp_result);
138 }
139
140 static void
141 do_page_tests (void)
142 {
143 char *s1, *s2;
144 int exp_result;
145 const size_t maxoffset = 64;
146
147 s1 = (char *) buf1 + BUF1PAGES * page_size - maxoffset;
148 memset (s1, 'a', maxoffset - 1);
149 s1[maxoffset - 1] = '\0';
150
151 s2 = (char *) buf2 + page_size - maxoffset;
152 memset (s2, 'a', maxoffset - 1);
153 s2[maxoffset - 1] = '\0';
154
155 /* At this point s1 and s2 point to distinct memory regions containing
156 "aa..." with size of 63 plus '\0'. Also, both strings are bounded to a
157 page with read/write access and the next page is protected with PROT_NONE
158 (meaning that any access outside of the page regions will trigger an
159 invalid memory access).
160
161 The loop checks for all possible offsets up to maxoffset for both
162 inputs with a size larger than the string (so memory access outside
163 the expected memory regions might trigger invalid access). */
164
165 for (size_t off1 = 0; off1 < maxoffset; off1++)
166 {
167 for (size_t off2 = 0; off2 < maxoffset; off2++)
168 {
169 exp_result = (off1 == off2)
170 ? 0
171 : off1 < off2
172 ? 'a'
173 : -'a';
174
175 FOR_EACH_IMPL (impl, 0)
176 check_result (impl, s1 + off1, s2 + off2, maxoffset + 1,
177 exp_result);
178 }
179 }
180 }
181
182 static void
183 do_random_tests (void)
184 {
185 size_t i, j, n, align1, align2, pos, len1, len2;
186 int result;
187 long r;
188 unsigned char *p1 = buf1 + page_size - 512;
189 unsigned char *p2 = buf2 + page_size - 512;
190
191 for (n = 0; n < ITERATIONS; n++)
192 {
193 align1 = random () & 31;
194 if (random () & 1)
195 align2 = random () & 31;
196 else
197 align2 = align1 + (random () & 24);
198 pos = random () & 511;
199 j = align1 > align2 ? align1 : align2;
200 if (pos + j >= 511)
201 pos = 510 - j - (random () & 7);
202 len1 = random () & 511;
203 if (pos >= len1 && (random () & 1))
204 len1 = pos + (random () & 7);
205 if (len1 + j >= 512)
206 len1 = 511 - j - (random () & 7);
207 if (pos >= len1)
208 len2 = len1;
209 else
210 len2 = len1 + (len1 != 511 - j ? random () % (511 - j - len1) : 0);
211 j = (pos > len2 ? pos : len2) + align1 + 64;
212 if (j > 512)
213 j = 512;
214 for (i = 0; i < j; ++i)
215 {
216 p1[i] = tolower (random () & 255);
217 if (i < len1 + align1 && !p1[i])
218 {
219 p1[i] = tolower (random () & 255);
220 if (!p1[i])
221 p1[i] = tolower (1 + (random () & 127));
222 }
223 }
224 for (i = 0; i < j; ++i)
225 {
226 p2[i] = toupper (random () & 255);
227 if (i < len2 + align2 && !p2[i])
228 {
229 p2[i] = toupper (random () & 255);
230 if (!p2[i])
231 toupper (p2[i] = 1 + (random () & 127));
232 }
233 }
234
235 result = 0;
236 memcpy (p2 + align2, p1 + align1, pos);
237 if (pos < len1)
238 {
239 if (tolower (p2[align2 + pos]) == p1[align1 + pos])
240 {
241 p2[align2 + pos] = toupper (random () & 255);
242 if (tolower (p2[align2 + pos]) == p1[align1 + pos])
243 p2[align2 + pos] = toupper (p1[align1 + pos]
244 + 3 + (random () & 127));
245 }
246
247 if (p1[align1 + pos] < tolower (p2[align2 + pos]))
248 result = -1;
249 else
250 result = 1;
251 }
252 p1[len1 + align1] = 0;
253 p2[len2 + align2] = 0;
254
255 FOR_EACH_IMPL (impl, 1)
256 {
257 r = CALL (impl, (char *) (p1 + align1), (char *) (p2 + align2),
258 pos + 1 + (random () & 255));
259 /* Test whether on 64-bit architectures where ABI requires
260 callee to promote has the promotion been done. */
261 asm ("" : "=g" (r) : "0" (r));
262 if ((r == 0 && result)
263 || (r < 0 && result >= 0)
264 || (r > 0 && result <= 0))
265 {
266 error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
267 n, impl->name, align1, align2, len1, len2, pos, r, result, p1, p2);
268 ret = 1;
269 }
270 }
271 }
272 }
273
274 /* Regression test for BZ #12205 */
275 static void
276 bz12205 (void)
277 {
278 static char cp [4096+16] __attribute__ ((aligned(4096)));
279 static char gotrel[4096] __attribute__ ((aligned(4096)));
280 char *s1 = cp + 0xffa;
281 char *s2 = gotrel + 0xcbe;
282 int exp_result;
283 size_t n = 6;
284
285 strcpy (s1, "gottpoff");
286 strcpy (s2, "GOTPLT");
287
288 exp_result = simple_strncasecmp (s1, s2, n);
289 FOR_EACH_IMPL (impl, 0)
290 check_result (impl, s1, s2, n, exp_result);
291 }
292
293 /* Regression test for BZ #14195 */
294 static void
295 bz14195 (void)
296 {
297 const char *empty_string = "";
298 FOR_EACH_IMPL (impl, 0)
299 check_result (impl, empty_string, "", 5, 0);
300 }
301
302 static void
303 test_locale (const char *locale)
304 {
305 size_t i;
306
307 if (setlocale (LC_CTYPE, locale) == NULL)
308 {
309 error (0, 0, "cannot set locale \"%s\"", locale);
310 ret = 1;
311 }
312
313 bz12205 ();
314 bz14195 ();
315
316 printf ("%23s", locale);
317 FOR_EACH_IMPL (impl, 0)
318 printf ("\t%s", impl->name);
319 putchar ('\n');
320
321 for (i = 1; i < 16; ++i)
322 {
323 do_test (i, i, i - 1, i, 127, 0);
324
325 do_test (i, i, i, i, 127, 0);
326 do_test (i, i, i, i, 127, 1);
327 do_test (i, i, i, i, 127, -1);
328
329 do_test (i, i, i + 1, i, 127, 0);
330 do_test (i, i, i + 1, i, 127, 1);
331 do_test (i, i, i + 1, i, 127, -1);
332 }
333
334 for (i = 1; i < 10; ++i)
335 {
336 do_test (0, 0, (2 << i) - 1, 2 << i, 127, 0);
337 do_test (0, 0, 2 << i, 2 << i, 254, 0);
338 do_test (0, 0, (2 << i) + 1, 2 << i, 127, 0);
339
340 do_test (0, 0, (2 << i) + 1, 2 << i, 254, 0);
341
342 do_test (0, 0, 2 << i, 2 << i, 127, 1);
343 do_test (0, 0, (2 << i) + 10, 2 << i, 127, 1);
344
345 do_test (0, 0, 2 << i, 2 << i, 254, 1);
346 do_test (0, 0, (2 << i) + 10, 2 << i, 254, 1);
347
348 do_test (0, 0, 2 << i, 2 << i, 127, -1);
349 do_test (0, 0, (2 << i) + 10, 2 << i, 127, -1);
350
351 do_test (0, 0, 2 << i, 2 << i, 254, -1);
352 do_test (0, 0, (2 << i) + 10, 2 << i, 254, -1);
353 }
354
355 for (i = 1; i < 8; ++i)
356 {
357 do_test (i, 2 * i, (8 << i) - 1, 8 << i, 127, 0);
358 do_test (i, 2 * i, 8 << i, 8 << i, 127, 0);
359 do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, 0);
360
361 do_test (2 * i, i, (8 << i) - 1, 8 << i, 254, 0);
362 do_test (2 * i, i, 8 << i, 8 << i, 254, 0);
363 do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, 0);
364
365 do_test (i, 2 * i, 8 << i, 8 << i, 127, 1);
366 do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, 1);
367
368 do_test (2 * i, i, 8 << i, 8 << i, 254, 1);
369 do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, 1);
370
371 do_test (i, 2 * i, 8 << i, 8 << i, 127, -1);
372 do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, -1);
373
374 do_test (2 * i, i, 8 << i, 8 << i, 254, -1);
375 do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, -1);
376 }
377
378 do_random_tests ();
379 do_page_tests ();
380 }
381
382 int
383 test_main (void)
384 {
385 test_init ();
386
387 test_locale ("C");
388 test_locale ("en_US.ISO-8859-1");
389 test_locale ("en_US.UTF-8");
390 test_locale ("tr_TR.ISO-8859-9");
391 test_locale ("tr_TR.UTF-8");
392
393 return ret;
394 }
395
396 #include <support/test-driver.c>