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.
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/>. */
22 #define TEST_NAME "strncasecmp"
23 #include "test-string.h"
25 typedef int (*proto_t
) (const char *, const char *, size_t);
26 static int simple_strncasecmp (const char *, const char *, size_t);
27 static int stupid_strncasecmp (const char *, const char *, size_t);
29 IMPL (stupid_strncasecmp
, 0)
30 IMPL (simple_strncasecmp
, 0)
34 simple_strncasecmp (const char *s1
, const char *s2
, size_t n
)
41 while ((ret
= ((unsigned char) tolower (*s1
)
42 - (unsigned char) tolower (*s2
))) == 0
53 stupid_strncasecmp (const char *s1
, const char *s2
, size_t max
)
55 size_t ns1
= strlen (s1
) + 1;
56 size_t ns2
= strlen (s2
) + 1;
57 size_t n
= ns1
< ns2
? ns1
: ns2
;
64 if ((ret
= ((unsigned char) tolower (*s1
)
65 - (unsigned char) tolower (*s2
))) != 0)
74 check_result (impl_t
*impl
, const char *s1
, const char *s2
, size_t n
,
77 int result
= CALL (impl
, s1
, s2
, n
);
78 if ((exp_result
== 0 && result
!= 0)
79 || (exp_result
< 0 && result
>= 0)
80 || (exp_result
> 0 && result
<= 0))
82 error (0, 0, "Wrong result in function %s %d %d", impl
->name
,
92 do_one_test (impl_t
*impl
, const char *s1
, const char *s2
, size_t n
,
95 if (check_result (impl
, s1
, s2
, n
, exp_result
) < 0)
100 do_test (size_t align1
, size_t align2
, size_t n
, size_t len
, int max_char
,
110 if (align1
+ len
+ 1 >= page_size
)
114 if (align2
+ len
+ 1 >= page_size
)
117 s1
= (char *) (buf1
+ align1
);
118 s2
= (char *) (buf2
+ align2
);
120 for (i
= 0; i
< len
; i
++)
122 s1
[i
] = toupper (1 + 23 * i
% max_char
);
123 s2
[i
] = tolower (s1
[i
]);
126 s1
[len
] = s2
[len
] = 0;
128 s2
[len
+ 1] = 24 + exp_result
;
129 if ((s2
[len
- 1] == 'z' && exp_result
== -1)
130 || (s2
[len
- 1] == 'a' && exp_result
== 1))
131 s1
[len
- 1] += exp_result
;
133 s2
[len
- 1] -= exp_result
;
135 FOR_EACH_IMPL (impl
, 0)
136 do_one_test (impl
, s1
, s2
, n
, exp_result
);
144 const size_t maxoffset
= 64;
146 s1
= (char *) buf1
+ BUF1PAGES
* page_size
- maxoffset
;
147 memset (s1
, 'a', maxoffset
- 1);
148 s1
[maxoffset
- 1] = '\0';
150 s2
= (char *) buf2
+ page_size
- maxoffset
;
151 memset (s2
, 'a', maxoffset
- 1);
152 s2
[maxoffset
- 1] = '\0';
154 /* At this point s1 and s2 point to distinct memory regions containing
155 "aa..." with size of 63 plus '\0'. Also, both strings are bounded to a
156 page with read/write access and the next page is protected with PROT_NONE
157 (meaning that any access outside of the page regions will trigger an
158 invalid memory access).
160 The loop checks for all possible offsets up to maxoffset for both
161 inputs with a size larger than the string (so memory access outside
162 the expected memory regions might trigger invalid access). */
164 for (size_t off1
= 0; off1
< maxoffset
; off1
++)
166 for (size_t off2
= 0; off2
< maxoffset
; off2
++)
168 exp_result
= (off1
== off2
)
174 FOR_EACH_IMPL (impl
, 0)
175 check_result (impl
, s1
+ off1
, s2
+ off2
, maxoffset
+ 1,
182 do_random_tests (void)
184 size_t i
, j
, n
, align1
, align2
, pos
, len1
, len2
;
187 unsigned char *p1
= buf1
+ page_size
- 512;
188 unsigned char *p2
= buf2
+ page_size
- 512;
190 for (n
= 0; n
< ITERATIONS
; n
++)
192 align1
= random () & 31;
194 align2
= random () & 31;
196 align2
= align1
+ (random () & 24);
197 pos
= random () & 511;
198 j
= align1
> align2
? align1
: align2
;
200 pos
= 510 - j
- (random () & 7);
201 len1
= random () & 511;
202 if (pos
>= len1
&& (random () & 1))
203 len1
= pos
+ (random () & 7);
205 len1
= 511 - j
- (random () & 7);
209 len2
= len1
+ (len1
!= 511 - j
? random () % (511 - j
- len1
) : 0);
210 j
= (pos
> len2
? pos
: len2
) + align1
+ 64;
213 for (i
= 0; i
< j
; ++i
)
215 p1
[i
] = tolower (random () & 255);
216 if (i
< len1
+ align1
&& !p1
[i
])
218 p1
[i
] = tolower (random () & 255);
220 p1
[i
] = tolower (1 + (random () & 127));
223 for (i
= 0; i
< j
; ++i
)
225 p2
[i
] = toupper (random () & 255);
226 if (i
< len2
+ align2
&& !p2
[i
])
228 p2
[i
] = toupper (random () & 255);
230 toupper (p2
[i
] = 1 + (random () & 127));
235 memcpy (p2
+ align2
, p1
+ align1
, pos
);
238 if (tolower (p2
[align2
+ pos
]) == p1
[align1
+ pos
])
240 p2
[align2
+ pos
] = toupper (random () & 255);
241 if (tolower (p2
[align2
+ pos
]) == p1
[align1
+ pos
])
242 p2
[align2
+ pos
] = toupper (p1
[align1
+ pos
]
243 + 3 + (random () & 127));
246 if (p1
[align1
+ pos
] < tolower (p2
[align2
+ pos
]))
251 p1
[len1
+ align1
] = 0;
252 p2
[len2
+ align2
] = 0;
254 FOR_EACH_IMPL (impl
, 1)
256 r
= CALL (impl
, (char *) (p1
+ align1
), (char *) (p2
+ align2
),
257 pos
+ 1 + (random () & 255));
258 /* Test whether on 64-bit architectures where ABI requires
259 callee to promote has the promotion been done. */
260 asm ("" : "=g" (r
) : "0" (r
));
261 if ((r
== 0 && result
)
262 || (r
< 0 && result
>= 0)
263 || (r
> 0 && result
<= 0))
265 error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
266 n
, impl
->name
, align1
, align2
, len1
, len2
, pos
, r
, result
, p1
, p2
);
273 /* Regression test for BZ #12205 */
277 static char cp
[4096+16] __attribute__ ((aligned(4096)));
278 static char gotrel
[4096] __attribute__ ((aligned(4096)));
279 char *s1
= cp
+ 0xffa;
280 char *s2
= gotrel
+ 0xcbe;
284 strcpy (s1
, "gottpoff");
285 strcpy (s2
, "GOTPLT");
287 exp_result
= simple_strncasecmp (s1
, s2
, n
);
288 FOR_EACH_IMPL (impl
, 0)
289 check_result (impl
, s1
, s2
, n
, exp_result
);
292 /* Regression test for BZ #14195 */
296 const char *empty_string
= "";
297 FOR_EACH_IMPL (impl
, 0)
298 check_result (impl
, empty_string
, "", 5, 0);
302 test_locale (const char *locale
)
306 if (setlocale (LC_CTYPE
, locale
) == NULL
)
308 error (0, 0, "cannot set locale \"%s\"", locale
);
315 printf ("%23s", locale
);
316 FOR_EACH_IMPL (impl
, 0)
317 printf ("\t%s", impl
->name
);
320 for (i
= 1; i
< 16; ++i
)
322 do_test (i
, i
, i
- 1, i
, 127, 0);
324 do_test (i
, i
, i
, i
, 127, 0);
325 do_test (i
, i
, i
, i
, 127, 1);
326 do_test (i
, i
, i
, i
, 127, -1);
328 do_test (i
, i
, i
+ 1, i
, 127, 0);
329 do_test (i
, i
, i
+ 1, i
, 127, 1);
330 do_test (i
, i
, i
+ 1, i
, 127, -1);
333 for (i
= 1; i
< 10; ++i
)
335 do_test (0, 0, (2 << i
) - 1, 2 << i
, 127, 0);
336 do_test (0, 0, 2 << i
, 2 << i
, 254, 0);
337 do_test (0, 0, (2 << i
) + 1, 2 << i
, 127, 0);
339 do_test (0, 0, (2 << i
) + 1, 2 << i
, 254, 0);
341 do_test (0, 0, 2 << i
, 2 << i
, 127, 1);
342 do_test (0, 0, (2 << i
) + 10, 2 << i
, 127, 1);
344 do_test (0, 0, 2 << i
, 2 << i
, 254, 1);
345 do_test (0, 0, (2 << i
) + 10, 2 << i
, 254, 1);
347 do_test (0, 0, 2 << i
, 2 << i
, 127, -1);
348 do_test (0, 0, (2 << i
) + 10, 2 << i
, 127, -1);
350 do_test (0, 0, 2 << i
, 2 << i
, 254, -1);
351 do_test (0, 0, (2 << i
) + 10, 2 << i
, 254, -1);
354 for (i
= 1; i
< 8; ++i
)
356 do_test (i
, 2 * i
, (8 << i
) - 1, 8 << i
, 127, 0);
357 do_test (i
, 2 * i
, 8 << i
, 8 << i
, 127, 0);
358 do_test (i
, 2 * i
, (8 << i
) + 100, 8 << i
, 127, 0);
360 do_test (2 * i
, i
, (8 << i
) - 1, 8 << i
, 254, 0);
361 do_test (2 * i
, i
, 8 << i
, 8 << i
, 254, 0);
362 do_test (2 * i
, i
, (8 << i
) + 100, 8 << i
, 254, 0);
364 do_test (i
, 2 * i
, 8 << i
, 8 << i
, 127, 1);
365 do_test (i
, 2 * i
, (8 << i
) + 100, 8 << i
, 127, 1);
367 do_test (2 * i
, i
, 8 << i
, 8 << i
, 254, 1);
368 do_test (2 * i
, i
, (8 << i
) + 100, 8 << i
, 254, 1);
370 do_test (i
, 2 * i
, 8 << i
, 8 << i
, 127, -1);
371 do_test (i
, 2 * i
, (8 << i
) + 100, 8 << i
, 127, -1);
373 do_test (2 * i
, i
, 8 << i
, 8 << i
, 254, -1);
374 do_test (2 * i
, i
, (8 << i
) + 100, 8 << i
, 254, -1);
387 test_locale ("en_US.ISO-8859-1");
388 test_locale ("en_US.UTF-8");
389 test_locale ("tr_TR.ISO-8859-9");
390 test_locale ("tr_TR.UTF-8");
395 #include <support/test-driver.c>