1 /* Test for string function add boundaries of usable memory.
2 Copyright (C) 1996-2023 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/>. */
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
30 #include <sys/param.h>
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
53 #define STRINGIFY(s) STRINGIFY2 (s)
54 #define STRINGIFY2(s) #s
60 size_t size = sysconf (_SC_PAGESIZE);
61 size_t nchars = size / sizeof (CHAR);
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)
73 puts ("No test, mmap not available.");
76 printf ("mmap failed: %m");
82 size_t inner, middle, outer, nchars64, max128;
85 nchars64 = nchars - 64;
90 max128 = nchars - 128;
94 mprotect (adr, size, PROT_NONE);
95 mprotect (adr + 2 * nchars, size, PROT_NONE);
98 mprotect (dest, size, PROT_NONE);
99 mprotect (dest + 2 * nchars, size, PROT_NONE);
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);
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);
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);
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)
174 && (cp - &adr[outer]) != middle - outer))
176 printf ("%s flunked for outer = %zu, middle = %zu, "
178 STRINGIFY (STRCHR), outer, middle, inner);
183 adr[middle] = L('T');
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",
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)
213 && (cp - &adr[outer]) != middle - outer))
215 printf ("%s flunked for outer = %zu, middle = %zu, "
217 STRINGIFY (STRRCHR), outer, middle, inner);
222 adr[middle] = L('T');
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);
245 adr[middle] = L('T');
250 for (outer = nchars; outer >= max128; --outer)
252 CHAR *cp = MEMCHR (&adr[outer], L('V'), nchars - outer);
256 printf ("%s flunked for outer = %zu\n",
257 STRINGIFY (MEMCHR), outer);
264 /* These functions only exist for single-byte characters. */
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);
282 adr[middle] = L('T');
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);
304 adr[middle] = L('T');
309 for (outer = nchars; outer >= max128; --outer)
311 CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
315 printf ("%s flunked for outer = %zu\n",
316 STRINGIFY (memrchr), outer);
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);
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);
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);
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);
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);
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, "
384 STRINGIFY (STRNCMP), outer, middle, inner);
388 if (STRNCMP (dest + nchars - outer, adr + middle, inner) != 0)
390 printf ("%s 2 flunked for outer = %zu, middle = %zu, "
392 STRINGIFY (STRNCMP), outer, middle, inner);
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);
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);
412 /* strncpy/wcsncpy tests */
413 adr[nchars - 1] = L('T');
414 for (outer = nchars; outer >= max128; --outer)
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);
431 adr[nchars - 1] = L('\0');
433 for (outer = nchars - 1; outer >= max128; --outer)
435 for (inner = MAX (outer, nchars64); inner < nchars; ++inner)
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, "
451 STRINGIFY (STRNCPY), outer, inner, len);
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, "
462 STRINGIFY (STRNCPY), outer, inner, len);
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);
493 /* stpncpy/wcpncpy test */
494 adr[nchars - 1] = L('T');
495 for (outer = nchars; outer >= max128; --outer)
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);
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, "
527 STRINGIFY (STPNCPY), outer, middle, inner);
532 adr[middle] = L('T');
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);
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);
566 /* This function only exists for single-byte characters. */
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",
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)
595 memccpy flunked partial copy for outer = %zu, middle = %zu, inner = %zu\n",
596 outer, middle, inner);
599 else if (dest[inner + 1] != L('\2'))
602 memccpy copied too much for outer = %zu, middle = %zu, inner = %zu\n",
603 outer, middle, inner);
606 adr[outer + inner] = L('\0');
618 #include <support/test-driver.c>