1 /* Test for string function add boundaries of usable memory.
2 Copyright (C) 1996-2020 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
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.
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.
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/>. */
22 /* Make sure we don't test the optimized inline functions if we want to
23 test the real implementation. */
24 #undef __USE_STRING_INLINES
31 #include <sys/param.h>
36 # define MEMSET memset
37 # define STRLEN strlen
38 # define STRNLEN strnlen
39 # define STRCHR strchr
40 # define STRRCHR strrchr
41 # define STRCPY strcpy
42 # define STRNCPY strncpy
43 # define MEMCMP memcmp
44 # define STPCPY stpcpy
45 # define STPNCPY stpncpy
46 # define MEMCPY memcpy
47 # define MEMPCPY mempcpy
48 # define MEMCHR memchr
49 # define STRCMP strcmp
50 # define STRNCMP strncmp
54 #define STRINGIFY(s) STRINGIFY2 (s)
55 #define STRINGIFY2(s) #s
61 size_t size
= sysconf (_SC_PAGESIZE
);
62 size_t nchars
= size
/ sizeof (CHAR
);
67 adr
= (CHAR
*) mmap (NULL
, 3 * size
, PROT_READ
| PROT_WRITE
,
68 MAP_PRIVATE
| MAP_ANON
, -1, 0);
69 dest
= (CHAR
*) mmap (NULL
, 3 * size
, PROT_READ
| PROT_WRITE
,
70 MAP_PRIVATE
| MAP_ANON
, -1, 0);
71 if (adr
== MAP_FAILED
|| dest
== MAP_FAILED
)
74 puts ("No test, mmap not available.");
77 printf ("mmap failed: %m");
83 size_t inner
, middle
, outer
, nchars64
, max128
;
86 nchars64
= nchars
- 64;
91 max128
= nchars
- 128;
95 mprotect (adr
, size
, PROT_NONE
);
96 mprotect (adr
+ 2 * nchars
, size
, PROT_NONE
);
99 mprotect (dest
, size
, PROT_NONE
);
100 mprotect (dest
+ 2 * nchars
, size
, PROT_NONE
);
103 MEMSET (adr
, L('T'), nchars
);
105 /* strlen/wcslen test */
106 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
108 for (inner
= MAX (outer
, nchars64
); inner
< nchars
; ++inner
)
110 adr
[inner
] = L('\0');
112 if (STRLEN (&adr
[outer
]) != (size_t) (inner
- outer
))
114 printf ("%s flunked for outer = %zu, inner = %zu\n",
115 STRINGIFY (STRLEN
), outer
, inner
);
125 /* strnlen/wcsnlen test */
126 for (outer
= nchars
; outer
>= max128
; --outer
)
128 for (inner
= MAX (outer
, nchars64
); inner
< nchars
; ++inner
)
130 adr
[inner
] = L('\0');
132 if (STRNLEN (&adr
[outer
], inner
- outer
+ 1)
133 != (size_t) (inner
- outer
))
135 printf ("%s flunked for outer = %zu, inner = %zu\n",
136 STRINGIFY (STRNLEN
), outer
, inner
);
145 for (outer
= nchars
; outer
>= max128
; --outer
)
147 for (inner
= MAX (outer
, nchars64
); inner
<= nchars
; ++inner
)
149 if (STRNLEN (&adr
[outer
], inner
- outer
)
150 != (size_t) (inner
- outer
))
152 printf ("%s flunked bounded for outer = %zu, inner = %zu\n",
153 STRINGIFY (STRNLEN
), outer
, inner
);
161 /* strchr/wcschr test */
162 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
164 for (middle
= MAX (outer
, nchars64
); middle
< nchars
; ++middle
)
166 for (inner
= middle
; inner
< nchars
; ++inner
)
168 adr
[middle
] = L('V');
169 adr
[inner
] = L('\0');
171 CHAR
*cp
= STRCHR (&adr
[outer
], L('V'));
173 if ((inner
== middle
&& cp
!= NULL
)
175 && (cp
- &adr
[outer
]) != middle
- outer
))
177 printf ("%s flunked for outer = %zu, middle = %zu, "
179 STRINGIFY (STRCHR
), outer
, middle
, inner
);
184 adr
[middle
] = L('T');
192 adr
[nchars
- 1] = L('\0');
193 if (STRCHR (&adr
[nchars
- 1], L('\n')) != NULL
)
195 printf ("%s flunked test of empty string at end of page\n",
200 /* strrchr/wcsrchr test */
201 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
203 for (middle
= MAX (outer
, nchars64
); middle
< nchars
; ++middle
)
205 for (inner
= middle
; inner
< nchars
; ++inner
)
207 adr
[middle
] = L('V');
208 adr
[inner
] = L('\0');
210 CHAR
*cp
= STRRCHR (&adr
[outer
], L('V'));
212 if ((inner
== middle
&& cp
!= NULL
)
214 && (cp
- &adr
[outer
]) != middle
- outer
))
216 printf ("%s flunked for outer = %zu, middle = %zu, "
218 STRINGIFY (STRRCHR
), outer
, middle
, inner
);
223 adr
[middle
] = L('T');
231 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
233 for (middle
= MAX (outer
, nchars64
); middle
< nchars
; ++middle
)
235 adr
[middle
] = L('V');
237 CHAR
*cp
= MEMCHR (&adr
[outer
], L('V'), 3 * size
);
239 if (cp
- &adr
[outer
] != middle
- outer
)
241 printf ("%s flunked for outer = %zu, middle = %zu\n",
242 STRINGIFY (MEMCHR
), outer
, middle
);
246 adr
[middle
] = L('T');
251 for (outer
= nchars
; outer
>= max128
; --outer
)
253 CHAR
*cp
= MEMCHR (&adr
[outer
], L('V'), nchars
- outer
);
257 printf ("%s flunked for outer = %zu\n",
258 STRINGIFY (MEMCHR
), outer
);
265 /* These functions only exist for single-byte characters. */
268 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
270 for (middle
= MAX (outer
, nchars64
); middle
< nchars
; ++middle
)
272 adr
[middle
] = L('V');
274 CHAR
*cp
= rawmemchr (&adr
[outer
], L('V'));
276 if (cp
- &adr
[outer
] != middle
- outer
)
278 printf ("%s flunked for outer = %zu, middle = %zu\n",
279 STRINGIFY (rawmemchr
), outer
, middle
);
283 adr
[middle
] = L('T');
290 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
292 for (middle
= MAX (outer
, nchars64
); middle
< nchars
; ++middle
)
294 adr
[middle
] = L('V');
296 CHAR
*cp
= memrchr (&adr
[outer
], L('V'), nchars
- outer
);
298 if (cp
- &adr
[outer
] != middle
- outer
)
300 printf ("%s flunked for outer = %zu, middle = %zu\n",
301 STRINGIFY (memrchr
), outer
, middle
);
305 adr
[middle
] = L('T');
310 for (outer
= nchars
; outer
>= max128
; --outer
)
312 CHAR
*cp
= memrchr (&adr
[outer
], L('V'), nchars
- outer
);
316 printf ("%s flunked for outer = %zu\n",
317 STRINGIFY (memrchr
), outer
);
325 /* strcpy/wcscpy test */
326 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
328 for (inner
= MAX (outer
, nchars64
); inner
< nchars
; ++inner
)
330 adr
[inner
] = L('\0');
332 if (STRCPY (dest
, &adr
[outer
]) != dest
333 || STRLEN (dest
) != (size_t) (inner
- outer
))
335 printf ("%s flunked for outer = %zu, inner = %zu\n",
336 STRINGIFY (STRCPY
), outer
, inner
);
346 /* strcmp/wcscmp tests */
347 for (outer
= 1; outer
< 32; ++outer
)
348 for (middle
= 0; middle
< 16; ++middle
)
350 MEMSET (adr
+ middle
, L('T'), 256);
352 MEMSET (dest
+ nchars
- outer
, L('T'), outer
- 1);
353 dest
[nchars
- 1] = L('\0');
355 if (STRCMP (adr
+ middle
, dest
+ nchars
- outer
) <= 0)
357 printf ("%s 1 flunked for outer = %zu, middle = %zu\n",
358 STRINGIFY (STRCMP
), outer
, middle
);
362 if (STRCMP (dest
+ nchars
- outer
, adr
+ middle
) >= 0)
364 printf ("%s 2 flunked for outer = %zu, middle = %zu\n",
365 STRINGIFY (STRCMP
), outer
, middle
);
370 /* strncmp/wcsncmp tests */
371 for (outer
= 1; outer
< 32; ++outer
)
372 for (middle
= 0; middle
< 16; ++middle
)
374 MEMSET (adr
+ middle
, L('T'), 256);
376 MEMSET (dest
+ nchars
- outer
, L('T'), outer
- 1);
377 dest
[nchars
- 1] = L('U');
379 for (inner
= 0; inner
< outer
; ++inner
)
381 if (STRNCMP (adr
+ middle
, dest
+ nchars
- outer
, inner
) != 0)
383 printf ("%s 1 flunked for outer = %zu, middle = %zu, "
385 STRINGIFY (STRNCMP
), outer
, middle
, inner
);
389 if (STRNCMP (dest
+ nchars
- outer
, adr
+ middle
, inner
) != 0)
391 printf ("%s 2 flunked for outer = %zu, middle = %zu, "
393 STRINGIFY (STRNCMP
), outer
, middle
, inner
);
398 if (STRNCMP (adr
+ middle
, dest
+ nchars
- outer
, outer
) >= 0)
400 printf ("%s 1 flunked for outer = %zu, middle = %zu, full\n",
401 STRINGIFY (STRNCMP
), outer
, middle
);
405 if (STRNCMP (dest
+ nchars
- outer
, adr
+ middle
, outer
) <= 0)
407 printf ("%s 2 flunked for outer = %zu, middle = %zu, full\n",
408 STRINGIFY (STRNCMP
), outer
, middle
);
413 /* strncpy/wcsncpy tests */
414 adr
[nchars
- 1] = L('T');
415 for (outer
= nchars
; outer
>= max128
; --outer
)
419 for (len
= 0; len
< nchars
- outer
; ++len
)
421 if (STRNCPY (dest
, &adr
[outer
], len
) != dest
422 || MEMCMP (dest
, &adr
[outer
], len
) != 0)
424 printf ("outer %s flunked for outer = %zu, len = %zu\n",
425 STRINGIFY (STRNCPY
), outer
, len
);
432 adr
[nchars
- 1] = L('\0');
434 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
436 for (inner
= MAX (outer
, nchars64
); inner
< nchars
; ++inner
)
440 adr
[inner
] = L('\0');
442 for (len
= 0; len
< nchars
- outer
+ 64; ++len
)
444 if (STRNCPY (dest
, &adr
[outer
], len
) != dest
445 || MEMCMP (dest
, &adr
[outer
],
446 MIN (inner
- outer
, len
)) != 0
447 || (inner
- outer
< len
448 && STRLEN (dest
) != (inner
- outer
)))
450 printf ("%s flunked for outer = %zu, inner = %zu, "
452 STRINGIFY (STRNCPY
), outer
, inner
, len
);
455 if (STRNCPY (dest
+ 1, &adr
[outer
], len
) != dest
+ 1
456 || MEMCMP (dest
+ 1, &adr
[outer
],
457 MIN (inner
- outer
, len
)) != 0
458 || (inner
- outer
< len
459 && STRLEN (dest
+ 1) != (inner
- outer
)))
461 printf ("%s+1 flunked for outer = %zu, inner = %zu, "
463 STRINGIFY (STRNCPY
), outer
, inner
, len
);
474 /* stpcpy/wcpcpy test */
475 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
477 for (inner
= MAX (outer
, nchars64
); inner
< nchars
; ++inner
)
479 adr
[inner
] = L('\0');
481 if ((STPCPY (dest
, &adr
[outer
]) - dest
) != inner
- outer
)
483 printf ("%s flunked for outer = %zu, inner = %zu\n",
484 STRINGIFY (STPCPY
), outer
, inner
);
494 /* stpncpy/wcpncpy test */
495 adr
[nchars
- 1] = L('T');
496 for (outer
= nchars
; outer
>= max128
; --outer
)
500 for (len
= 0; len
< nchars
- outer
; ++len
)
502 if (STPNCPY (dest
, &adr
[outer
], len
) != dest
+ len
503 || MEMCMP (dest
, &adr
[outer
], len
) != 0)
505 printf ("outer %s flunked for outer = %zu, len = %zu\n",
506 STRINGIFY (STPNCPY
), outer
, len
);
513 adr
[nchars
- 1] = L('\0');
515 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
517 for (middle
= MAX (outer
, nchars64
); middle
< nchars
; ++middle
)
519 adr
[middle
] = L('\0');
521 for (inner
= 0; inner
< nchars
- outer
; ++ inner
)
523 if ((STPNCPY (dest
, &adr
[outer
], inner
) - dest
)
524 != MIN (inner
, middle
- outer
))
526 printf ("%s flunked for outer = %zu, middle = %zu, "
528 STRINGIFY (STPNCPY
), outer
, middle
, inner
);
533 adr
[middle
] = L('T');
539 /* memcpy/wmemcpy test */
540 for (outer
= nchars
; outer
>= max128
; --outer
)
542 for (inner
= 0; inner
< nchars
- outer
; ++inner
)
543 if (MEMCPY (dest
, &adr
[outer
], inner
) != dest
)
545 printf ("%s flunked for outer = %zu, inner = %zu\n",
546 STRINGIFY (MEMCPY
), outer
, inner
);
553 /* mempcpy/wmempcpy test */
554 for (outer
= nchars
; outer
>= max128
; --outer
)
556 for (inner
= 0; inner
< nchars
- outer
; ++inner
)
557 if (MEMPCPY (dest
, &adr
[outer
], inner
) != dest
+ inner
)
559 printf ("%s flunked for outer = %zu, inner = %zu\n",
560 STRINGIFY (MEMPCPY
), outer
, inner
);
567 /* This function only exists for single-byte characters. */
570 memset (adr
, '\0', nchars
);
571 for (outer
= nchars
; outer
>= max128
; --outer
)
573 for (inner
= 0; inner
< nchars
- outer
; ++inner
)
574 if (memccpy (dest
, &adr
[outer
], L('\1'), inner
) != NULL
)
576 printf ("memccpy flunked full copy for outer = %zu, inner = %zu\n",
583 for (outer
= nchars
- 1; outer
>= max128
; --outer
)
585 for (middle
= 0; middle
< nchars
- outer
; ++middle
)
587 memset (dest
, L('\2'), middle
+ 1);
588 for (inner
= 0; inner
< middle
; ++inner
)
590 adr
[outer
+ inner
] = L('\1');
592 if (memccpy (dest
, &adr
[outer
], '\1', middle
+ 128)
596 memccpy flunked partial copy for outer = %zu, middle = %zu, inner = %zu\n",
597 outer
, middle
, inner
);
600 else if (dest
[inner
+ 1] != L('\2'))
603 memccpy copied too much for outer = %zu, middle = %zu, inner = %zu\n",
604 outer
, middle
, inner
);
607 adr
[outer
+ inner
] = L('\0');
619 #include <support/test-driver.c>