1 /* Test for string function add boundaries of usable memory.
2 Copyright (C) 1996-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/>. */
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>