syslog: Improve fortify with clang
[glibc.git] / string / stratcliff.c
blobab213b80a0f9304d7e9be77542d46aa2315f2f00
1 /* Test for string function add boundaries of usable memory.
2 Copyright (C) 1996-2024 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 #define _GNU_SOURCE 1
21 /* Make sure we don't test the optimized inline functions if we want to
22 test the real implementation. */
23 #undef __USE_STRING_INLINES
25 #include <errno.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/mman.h>
30 #include <sys/param.h>
32 #ifndef CHAR
33 # define L(c) c
34 # define CHAR char
35 # define MEMSET memset
36 # define STRLEN strlen
37 # define STRNLEN strnlen
38 # define STRCHR strchr
39 # define STRRCHR strrchr
40 # define STRCPY strcpy
41 # define STRNCPY strncpy
42 # define MEMCMP memcmp
43 # define STPCPY stpcpy
44 # define STPNCPY stpncpy
45 # define MEMCPY memcpy
46 # define MEMPCPY mempcpy
47 # define MEMCHR memchr
48 # define STRCMP strcmp
49 # define STRNCMP strncmp
50 #endif
53 #define STRINGIFY(s) STRINGIFY2 (s)
54 #define STRINGIFY2(s) #s
57 int
58 do_test (void)
60 size_t size = sysconf (_SC_PAGESIZE);
61 size_t nchars = size / sizeof (CHAR);
62 CHAR *adr;
63 CHAR *dest;
64 int result = 0;
66 adr = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
67 MAP_PRIVATE | MAP_ANON, -1, 0);
68 dest = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
69 MAP_PRIVATE | MAP_ANON, -1, 0);
70 if (adr == MAP_FAILED || dest == MAP_FAILED)
72 if (errno == ENOSYS)
73 puts ("No test, mmap not available.");
74 else
76 printf ("mmap failed: %m");
77 result = 1;
80 else
82 size_t inner, middle, outer, nchars64, max128;
84 if (nchars > 64)
85 nchars64 = nchars - 64;
86 else
87 nchars64 = 0;
89 if (nchars > 128)
90 max128 = nchars - 128;
91 else
92 max128 = 0;
94 mprotect (adr, size, PROT_NONE);
95 mprotect (adr + 2 * nchars, size, PROT_NONE);
96 adr += nchars;
98 mprotect (dest, size, PROT_NONE);
99 mprotect (dest + 2 * nchars, size, PROT_NONE);
100 dest += nchars;
102 MEMSET (adr, L('T'), nchars);
104 /* strlen/wcslen test */
105 for (outer = nchars - 1; outer >= max128; --outer)
107 for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
109 adr[inner] = L('\0');
111 if (STRLEN (&adr[outer]) != (size_t) (inner - outer))
113 printf ("%s flunked for outer = %zu, inner = %zu\n",
114 STRINGIFY (STRLEN), outer, inner);
115 result = 1;
118 adr[inner] = L('T');
120 if (outer == 0)
121 break;
124 /* strnlen/wcsnlen test */
125 for (outer = nchars; outer >= max128; --outer)
127 for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
129 adr[inner] = L('\0');
131 if (STRNLEN (&adr[outer], inner - outer + 1)
132 != (size_t) (inner - outer))
134 printf ("%s flunked for outer = %zu, inner = %zu\n",
135 STRINGIFY (STRNLEN), outer, inner);
136 result = 1;
139 adr[inner] = L('T');
141 if (outer == 0)
142 break;
144 for (outer = nchars; outer >= max128; --outer)
146 for (inner = MAX (outer, nchars64); inner <= nchars; ++inner)
148 if (STRNLEN (&adr[outer], inner - outer)
149 != (size_t) (inner - outer))
151 printf ("%s flunked bounded for outer = %zu, inner = %zu\n",
152 STRINGIFY (STRNLEN), outer, inner);
153 result = 1;
156 if (outer == 0)
157 break;
160 /* strchr/wcschr test */
161 for (outer = nchars - 1; outer >= max128; --outer)
163 for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
165 for (inner = middle; inner < nchars; ++inner)
167 adr[middle] = L('V');
168 adr[inner] = L('\0');
170 CHAR *cp = STRCHR (&adr[outer], L('V'));
172 if ((inner == middle && cp != NULL)
173 || (inner != middle
174 && (cp - &adr[outer]) != middle - outer))
176 printf ("%s flunked for outer = %zu, middle = %zu, "
177 "inner = %zu\n",
178 STRINGIFY (STRCHR), outer, middle, inner);
179 result = 1;
182 adr[inner] = L('T');
183 adr[middle] = L('T');
186 if (outer == 0)
187 break;
190 /* Special test. */
191 adr[nchars - 1] = L('\0');
192 if (STRCHR (&adr[nchars - 1], L('\n')) != NULL)
194 printf ("%s flunked test of empty string at end of page\n",
195 STRINGIFY (STRCHR));
196 result = 1;
199 /* strrchr/wcsrchr test */
200 for (outer = nchars - 1; outer >= max128; --outer)
202 for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
204 for (inner = middle; inner < nchars; ++inner)
206 adr[middle] = L('V');
207 adr[inner] = L('\0');
209 CHAR *cp = STRRCHR (&adr[outer], L('V'));
211 if ((inner == middle && cp != NULL)
212 || (inner != middle
213 && (cp - &adr[outer]) != middle - outer))
215 printf ("%s flunked for outer = %zu, middle = %zu, "
216 "inner = %zu\n",
217 STRINGIFY (STRRCHR), outer, middle, inner);
218 result = 1;
221 adr[inner] = L('T');
222 adr[middle] = L('T');
225 if (outer == 0)
226 break;
229 /* memchr test */
230 for (outer = nchars - 1; outer >= max128; --outer)
232 for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
234 adr[middle] = L('V');
236 CHAR *cp = MEMCHR (&adr[outer], L('V'), 3 * size);
238 if (cp - &adr[outer] != middle - outer)
240 printf ("%s flunked for outer = %zu, middle = %zu\n",
241 STRINGIFY (MEMCHR), outer, middle);
242 result = 1;
245 adr[middle] = L('T');
247 if (outer == 0)
248 break;
250 for (outer = nchars; outer >= max128; --outer)
252 CHAR *cp = MEMCHR (&adr[outer], L('V'), nchars - outer);
254 if (cp != NULL)
256 printf ("%s flunked for outer = %zu\n",
257 STRINGIFY (MEMCHR), outer);
258 result = 1;
260 if (outer == 0)
261 break;
264 /* These functions only exist for single-byte characters. */
265 #ifndef WCSTEST
266 /* rawmemchr test */
267 for (outer = nchars - 1; outer >= max128; --outer)
269 for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
271 adr[middle] = L('V');
273 CHAR *cp = rawmemchr (&adr[outer], L('V'));
275 if (cp - &adr[outer] != middle - outer)
277 printf ("%s flunked for outer = %zu, middle = %zu\n",
278 STRINGIFY (rawmemchr), outer, middle);
279 result = 1;
282 adr[middle] = L('T');
284 if (outer == 0)
285 break;
288 /* memrchr test */
289 for (outer = nchars - 1; outer >= max128; --outer)
291 for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
293 adr[middle] = L('V');
295 CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
297 if (cp - &adr[outer] != middle - outer)
299 printf ("%s flunked for outer = %zu, middle = %zu\n",
300 STRINGIFY (memrchr), outer, middle);
301 result = 1;
304 adr[middle] = L('T');
306 if (outer == 0)
307 break;
309 for (outer = nchars; outer >= max128; --outer)
311 CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
313 if (cp != NULL)
315 printf ("%s flunked for outer = %zu\n",
316 STRINGIFY (memrchr), outer);
317 result = 1;
319 if (outer == 0)
320 break;
322 #endif
324 /* strcpy/wcscpy test */
325 for (outer = nchars - 1; outer >= max128; --outer)
327 for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
329 adr[inner] = L('\0');
331 if (STRCPY (dest, &adr[outer]) != dest
332 || STRLEN (dest) != (size_t) (inner - outer))
334 printf ("%s flunked for outer = %zu, inner = %zu\n",
335 STRINGIFY (STRCPY), outer, inner);
336 result = 1;
339 adr[inner] = L('T');
341 if (outer == 0)
342 break;
345 /* strcmp/wcscmp tests */
346 for (outer = 1; outer < 32; ++outer)
347 for (middle = 0; middle < 16; ++middle)
349 MEMSET (adr + middle, L('T'), 256);
350 adr[256] = L('\0');
351 MEMSET (dest + nchars - outer, L('T'), outer - 1);
352 dest[nchars - 1] = L('\0');
354 if (STRCMP (adr + middle, dest + nchars - outer) <= 0)
356 printf ("%s 1 flunked for outer = %zu, middle = %zu\n",
357 STRINGIFY (STRCMP), outer, middle);
358 result = 1;
361 if (STRCMP (dest + nchars - outer, adr + middle) >= 0)
363 printf ("%s 2 flunked for outer = %zu, middle = %zu\n",
364 STRINGIFY (STRCMP), outer, middle);
365 result = 1;
369 /* strncmp/wcsncmp tests */
370 for (outer = 1; outer < 32; ++outer)
371 for (middle = 0; middle < 16; ++middle)
373 MEMSET (adr + middle, L('T'), 256);
374 adr[256] = L('\0');
375 MEMSET (dest + nchars - outer, L('T'), outer - 1);
376 dest[nchars - 1] = L('U');
378 for (inner = 0; inner < outer; ++inner)
380 if (STRNCMP (adr + middle, dest + nchars - outer, inner) != 0)
382 printf ("%s 1 flunked for outer = %zu, middle = %zu, "
383 "inner = %zu\n",
384 STRINGIFY (STRNCMP), outer, middle, inner);
385 result = 1;
388 if (STRNCMP (dest + nchars - outer, adr + middle, inner) != 0)
390 printf ("%s 2 flunked for outer = %zu, middle = %zu, "
391 "inner = %zu\n",
392 STRINGIFY (STRNCMP), outer, middle, inner);
393 result = 1;
397 if (STRNCMP (adr + middle, dest + nchars - outer, outer) >= 0)
399 printf ("%s 1 flunked for outer = %zu, middle = %zu, full\n",
400 STRINGIFY (STRNCMP), outer, middle);
401 result = 1;
404 if (STRNCMP (dest + nchars - outer, adr + middle, outer) <= 0)
406 printf ("%s 2 flunked for outer = %zu, middle = %zu, full\n",
407 STRINGIFY (STRNCMP), outer, middle);
408 result = 1;
412 /* strncpy/wcsncpy tests */
413 adr[nchars - 1] = L('T');
414 for (outer = nchars; outer >= max128; --outer)
416 size_t len;
418 for (len = 0; len < nchars - outer; ++len)
420 if (STRNCPY (dest, &adr[outer], len) != dest
421 || MEMCMP (dest, &adr[outer], len) != 0)
423 printf ("outer %s flunked for outer = %zu, len = %zu\n",
424 STRINGIFY (STRNCPY), outer, len);
425 result = 1;
428 if (outer == 0)
429 break;
431 adr[nchars - 1] = L('\0');
433 for (outer = nchars - 1; outer >= max128; --outer)
435 for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
437 size_t len;
439 adr[inner] = L('\0');
441 for (len = 0; len < nchars - outer + 64; ++len)
443 if (STRNCPY (dest, &adr[outer], len) != dest
444 || MEMCMP (dest, &adr[outer],
445 MIN (inner - outer, len)) != 0
446 || (inner - outer < len
447 && STRLEN (dest) != (inner - outer)))
449 printf ("%s flunked for outer = %zu, inner = %zu, "
450 "len = %zu\n",
451 STRINGIFY (STRNCPY), outer, inner, len);
452 result = 1;
454 if (STRNCPY (dest + 1, &adr[outer], len) != dest + 1
455 || MEMCMP (dest + 1, &adr[outer],
456 MIN (inner - outer, len)) != 0
457 || (inner - outer < len
458 && STRLEN (dest + 1) != (inner - outer)))
460 printf ("%s+1 flunked for outer = %zu, inner = %zu, "
461 "len = %zu\n",
462 STRINGIFY (STRNCPY), outer, inner, len);
463 result = 1;
467 adr[inner] = L('T');
469 if (outer == 0)
470 break;
473 /* stpcpy/wcpcpy test */
474 for (outer = nchars - 1; outer >= max128; --outer)
476 for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
478 adr[inner] = L('\0');
480 if ((STPCPY (dest, &adr[outer]) - dest) != inner - outer)
482 printf ("%s flunked for outer = %zu, inner = %zu\n",
483 STRINGIFY (STPCPY), outer, inner);
484 result = 1;
487 adr[inner] = L('T');
489 if (outer == 0)
490 break;
493 /* stpncpy/wcpncpy test */
494 adr[nchars - 1] = L('T');
495 for (outer = nchars; outer >= max128; --outer)
497 size_t len;
499 for (len = 0; len < nchars - outer; ++len)
501 if (STPNCPY (dest, &adr[outer], len) != dest + len
502 || MEMCMP (dest, &adr[outer], len) != 0)
504 printf ("outer %s flunked for outer = %zu, len = %zu\n",
505 STRINGIFY (STPNCPY), outer, len);
506 result = 1;
509 if (outer == 0)
510 break;
512 adr[nchars - 1] = L('\0');
514 for (outer = nchars - 1; outer >= max128; --outer)
516 for (middle = MAX (outer, nchars64); middle < nchars; ++middle)
518 adr[middle] = L('\0');
520 for (inner = 0; inner < nchars - outer; ++ inner)
522 if ((STPNCPY (dest, &adr[outer], inner) - dest)
523 != MIN (inner, middle - outer))
525 printf ("%s flunked for outer = %zu, middle = %zu, "
526 "inner = %zu\n",
527 STRINGIFY (STPNCPY), outer, middle, inner);
528 result = 1;
532 adr[middle] = L('T');
534 if (outer == 0)
535 break;
538 /* memcpy/wmemcpy test */
539 for (outer = nchars; outer >= max128; --outer)
541 for (inner = 0; inner < nchars - outer; ++inner)
542 if (MEMCPY (dest, &adr[outer], inner) != dest)
544 printf ("%s flunked for outer = %zu, inner = %zu\n",
545 STRINGIFY (MEMCPY), outer, inner);
546 result = 1;
548 if (outer == 0)
549 break;
552 /* mempcpy/wmempcpy test */
553 for (outer = nchars; outer >= max128; --outer)
555 for (inner = 0; inner < nchars - outer; ++inner)
556 if (MEMPCPY (dest, &adr[outer], inner) != dest + inner)
558 printf ("%s flunked for outer = %zu, inner = %zu\n",
559 STRINGIFY (MEMPCPY), outer, inner);
560 result = 1;
562 if (outer == 0)
563 break;
566 /* This function only exists for single-byte characters. */
567 #ifndef WCSTEST
568 /* memccpy test */
569 memset (adr, '\0', nchars);
570 for (outer = nchars; outer >= max128; --outer)
572 for (inner = 0; inner < nchars - outer; ++inner)
573 if (memccpy (dest, &adr[outer], L('\1'), inner) != NULL)
575 printf ("memccpy flunked full copy for outer = %zu, inner = %zu\n",
576 outer, inner);
577 result = 1;
579 if (outer == 0)
580 break;
582 for (outer = nchars - 1; outer >= max128; --outer)
584 for (middle = 0; middle < nchars - outer; ++middle)
586 memset (dest, L('\2'), middle + 1);
587 for (inner = 0; inner < middle; ++inner)
589 adr[outer + inner] = L('\1');
591 if (memccpy (dest, &adr[outer], '\1', middle + 128)
592 != dest + inner + 1)
594 printf ("\
595 memccpy flunked partial copy for outer = %zu, middle = %zu, inner = %zu\n",
596 outer, middle, inner);
597 result = 1;
599 else if (dest[inner + 1] != L('\2'))
601 printf ("\
602 memccpy copied too much for outer = %zu, middle = %zu, inner = %zu\n",
603 outer, middle, inner);
604 result = 1;
606 adr[outer + inner] = L('\0');
609 if (outer == 0)
610 break;
612 #endif
615 return result;
618 #include <support/test-driver.c>