mips: FIx clone3 implementation (BZ 31325)
[glibc.git] / string / tester.c
blob47f6aeba6ecdd50cedf23055714a15bae6508b95
1 /* Tester for string functions.
2 Copyright (C) 1995-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 #ifndef _GNU_SOURCE
20 #define _GNU_SOURCE
21 #endif
23 /* Make sure we don't test the optimized inline functions if we want to
24 test the real implementation. */
25 #if !defined DO_STRING_INLINES
26 #undef __USE_STRING_INLINES
27 #endif
29 #include <sys/cdefs.h>
30 #include <libc-diag.h>
32 /* Triggered by strncpy fortify wrapper when it is enabled. */
33 #if __GNUC_PREREQ (8, 0)
34 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation");
35 #endif
37 /* When building with fortify enabled, GCC < 12 issues a warning on the
38 fortify strncat wrapper might overflow the destination buffer (the
39 failure is tied to -Werror).
40 Triggered by strncat fortify wrapper when it is enabled. */
41 #if __GNUC_PREREQ (11, 0)
42 DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overread");
43 #endif
45 #include <errno.h>
46 #include <stdint.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <strings.h>
51 #include <fcntl.h>
53 /* This file tests a range of corner cases of string functions,
54 including cases where truncation occurs or where sizes specified
55 are larger than the actual buffers, which result in various
56 warnings. */
57 DIAG_IGNORE_NEEDS_COMMENT (8, "-Warray-bounds");
58 DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Wmemset-transposed-args");
59 #if __GNUC_PREREQ (7, 0)
60 DIAG_IGNORE_NEEDS_COMMENT (9, "-Wrestrict");
61 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
62 #endif
65 #define STREQ(a, b) (strcmp((a), (b)) == 0)
67 const char *it = "<UNSET>"; /* Routine name for message routines. */
68 size_t errors = 0;
70 /* Complain if condition is not true. */
71 static void
72 check (int thing, int number)
74 if (!thing)
76 printf ("%s flunked test %d\n", it, number);
77 ++errors;
81 /* Complain if first two args don't strcmp as equal. */
82 static void
83 equal (const char *a, const char *b, int number)
85 check (a != NULL && b != NULL && STREQ (a, b), number);
88 char one[50];
89 char two[50];
90 char *cp;
92 static void
93 test_strcmp (void)
95 it = "strcmp";
96 check (strcmp ("", "") == 0, 1); /* Trivial case. */
97 check (strcmp ("a", "a") == 0, 2); /* Identity. */
98 check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */
99 check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */
100 check (strcmp ("abcd", "abc") > 0, 5);
101 check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */
102 check (strcmp ("abce", "abcd") > 0, 7);
103 check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */
104 check (strcmp ("a\203", "a\003") > 0, 9);
107 char buf1[0x40], buf2[0x40];
108 int i, j;
109 for (i=0; i < 0x10; i++)
110 for (j = 0; j < 0x10; j++)
112 int k;
113 for (k = 0; k < 0x3f; k++)
115 buf1[k] = '0' ^ (k & 4);
116 buf2[k] = '4' ^ (k & 4);
118 buf1[i] = buf1[0x3f] = 0;
119 buf2[j] = buf2[0x3f] = 0;
120 for (k = 0; k < 0xf; k++)
122 int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
123 check (strcmp (buf1+i,buf2+j) == 0, cnum);
124 buf1[i+k] = 'A' + i + k;
125 buf1[i+k+1] = 0;
126 check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
127 check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
128 buf2[j+k] = 'B' + i + k;
129 buf2[j+k+1] = 0;
130 check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
131 check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
132 buf2[j+k] = 'A' + i + k;
133 buf1[i] = 'A' + i + 0x80;
134 check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
135 check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
136 buf1[i] = 'A' + i;
142 #define SIMPLE_COPY(fn, n, str, ntest) \
143 do { \
144 int __n; \
145 char *cp; \
146 for (__n = 0; __n < (int) sizeof (one); ++__n) \
147 one[__n] = 'Z'; \
148 fn (one, str); \
149 for (cp = one, __n = 0; __n < n; ++__n, ++cp) \
150 check (*cp == '0' + (n % 10), ntest); \
151 check (*cp == '\0', ntest); \
152 } while (0)
154 static void
155 test_strcpy (void)
157 int i;
158 it = "strcpy";
159 check (strcpy (one, "abcd") == one, 1); /* Returned value. */
160 equal (one, "abcd", 2); /* Basic test. */
162 (void) strcpy (one, "x");
163 equal (one, "x", 3); /* Writeover. */
164 equal (one+2, "cd", 4); /* Wrote too much? */
166 (void) strcpy (two, "hi there");
167 (void) strcpy (one, two);
168 equal (one, "hi there", 5); /* Basic test encore. */
169 equal (two, "hi there", 6); /* Stomped on source? */
171 (void) strcpy (one, "");
172 equal (one, "", 7); /* Boundary condition. */
174 for (i = 0; i < 16; i++)
176 (void) strcpy (one + i, "hi there"); /* Unaligned destination. */
177 equal (one + i, "hi there", 8 + (i * 2));
178 (void) strcpy (two, one + i); /* Unaligned source. */
179 equal (two, "hi there", 9 + (i * 2));
182 SIMPLE_COPY(strcpy, 0, "", 41);
183 SIMPLE_COPY(strcpy, 1, "1", 42);
184 SIMPLE_COPY(strcpy, 2, "22", 43);
185 SIMPLE_COPY(strcpy, 3, "333", 44);
186 SIMPLE_COPY(strcpy, 4, "4444", 45);
187 SIMPLE_COPY(strcpy, 5, "55555", 46);
188 SIMPLE_COPY(strcpy, 6, "666666", 47);
189 SIMPLE_COPY(strcpy, 7, "7777777", 48);
190 SIMPLE_COPY(strcpy, 8, "88888888", 49);
191 SIMPLE_COPY(strcpy, 9, "999999999", 50);
192 SIMPLE_COPY(strcpy, 10, "0000000000", 51);
193 SIMPLE_COPY(strcpy, 11, "11111111111", 52);
194 SIMPLE_COPY(strcpy, 12, "222222222222", 53);
195 SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
196 SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
197 SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
198 SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
200 /* Simple test using implicitly coerced `void *' arguments. */
201 const void *src = "frobozz";
202 void *dst = one;
203 check (strcpy (dst, src) == dst, 1);
204 equal (dst, "frobozz", 2);
207 static void
208 test_stpcpy (void)
210 it = "stpcpy";
211 check ((stpcpy (one, "a") - one) == 1, 1);
212 equal (one, "a", 2);
214 check ((stpcpy (one, "ab") - one) == 2, 3);
215 equal (one, "ab", 4);
217 check ((stpcpy (one, "abc") - one) == 3, 5);
218 equal (one, "abc", 6);
220 check ((stpcpy (one, "abcd") - one) == 4, 7);
221 equal (one, "abcd", 8);
223 check ((stpcpy (one, "abcde") - one) == 5, 9);
224 equal (one, "abcde", 10);
226 check ((stpcpy (one, "abcdef") - one) == 6, 11);
227 equal (one, "abcdef", 12);
229 check ((stpcpy (one, "abcdefg") - one) == 7, 13);
230 equal (one, "abcdefg", 14);
232 check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
233 equal (one, "abcdefgh", 16);
235 check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
236 equal (one, "abcdefghi", 18);
238 check ((stpcpy (one, "x") - one) == 1, 19);
239 equal (one, "x", 20); /* Writeover. */
240 equal (one+2, "cdefghi", 21); /* Wrote too much? */
242 check ((stpcpy (one, "xx") - one) == 2, 22);
243 equal (one, "xx", 23); /* Writeover. */
244 equal (one+3, "defghi", 24); /* Wrote too much? */
246 check ((stpcpy (one, "xxx") - one) == 3, 25);
247 equal (one, "xxx", 26); /* Writeover. */
248 equal (one+4, "efghi", 27); /* Wrote too much? */
250 check ((stpcpy (one, "xxxx") - one) == 4, 28);
251 equal (one, "xxxx", 29); /* Writeover. */
252 equal (one+5, "fghi", 30); /* Wrote too much? */
254 check ((stpcpy (one, "xxxxx") - one) == 5, 31);
255 equal (one, "xxxxx", 32); /* Writeover. */
256 equal (one+6, "ghi", 33); /* Wrote too much? */
258 check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
259 equal (one, "xxxxxx", 35); /* Writeover. */
260 equal (one+7, "hi", 36); /* Wrote too much? */
262 check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
263 equal (one, "xxxxxxx", 38); /* Writeover. */
264 equal (one+8, "i", 39); /* Wrote too much? */
266 check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
267 equal (one, "abc", 41);
268 equal (one + 4, "xxx", 42);
270 SIMPLE_COPY(stpcpy, 0, "", 43);
271 SIMPLE_COPY(stpcpy, 1, "1", 44);
272 SIMPLE_COPY(stpcpy, 2, "22", 45);
273 SIMPLE_COPY(stpcpy, 3, "333", 46);
274 SIMPLE_COPY(stpcpy, 4, "4444", 47);
275 SIMPLE_COPY(stpcpy, 5, "55555", 48);
276 SIMPLE_COPY(stpcpy, 6, "666666", 49);
277 SIMPLE_COPY(stpcpy, 7, "7777777", 50);
278 SIMPLE_COPY(stpcpy, 8, "88888888", 51);
279 SIMPLE_COPY(stpcpy, 9, "999999999", 52);
280 SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
281 SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
282 SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
283 SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
284 SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
285 SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
286 SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
289 static void
290 test_stpncpy (void)
292 it = "stpncpy";
293 memset (one, 'x', sizeof (one));
294 check (stpncpy (one, "abc", 2) == one + 2, 1);
295 check (stpncpy (one, "abc", 3) == one + 3, 2);
296 check (stpncpy (one, "abc", 4) == one + 3, 3);
297 check (one[3] == '\0' && one[4] == 'x', 4);
298 check (stpncpy (one, "abcd", 5) == one + 4, 5);
299 check (one[4] == '\0' && one[5] == 'x', 6);
300 check (stpncpy (one, "abcd", 6) == one + 4, 7);
301 check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
304 static void
305 test_strcat (void)
307 it = "strcat";
308 (void) strcpy (one, "ijk");
309 check (strcat (one, "lmn") == one, 1); /* Returned value. */
310 equal (one, "ijklmn", 2); /* Basic test. */
312 (void) strcpy (one, "x");
313 (void) strcat (one, "yz");
314 equal (one, "xyz", 3); /* Writeover. */
315 equal (one+4, "mn", 4); /* Wrote too much? */
317 (void) strcpy (one, "gh");
318 (void) strcpy (two, "ef");
319 (void) strcat (one, two);
320 equal (one, "ghef", 5); /* Basic test encore. */
321 equal (two, "ef", 6); /* Stomped on source? */
323 (void) strcpy (one, "");
324 (void) strcat (one, "");
325 equal (one, "", 7); /* Boundary conditions. */
326 (void) strcpy (one, "ab");
327 (void) strcat (one, "");
328 equal (one, "ab", 8);
329 (void) strcpy (one, "");
330 (void) strcat (one, "cd");
331 equal (one, "cd", 9);
333 int ntest = 10;
334 char buf1[80] __attribute__ ((aligned (16)));
335 char buf2[32] __attribute__ ((aligned (16)));
336 for (size_t n1 = 0; n1 < 16; ++n1)
337 for (size_t n2 = 0; n2 < 16; ++n2)
338 for (size_t n3 = 0; n3 < 32; ++n3)
340 size_t olderrors = errors;
342 memset (buf1, 'b', sizeof (buf1));
344 memset (buf1 + n2, 'a', n3);
345 buf1[n2 + n3] = '\0';
346 strcpy (buf2 + n1, "123");
348 check (strcat (buf1 + n2, buf2 + n1) == buf1 + n2, ntest);
349 if (errors == olderrors)
350 for (size_t i = 0; i < sizeof (buf1); ++i)
352 if (i < n2)
353 check (buf1[i] == 'b', ntest);
354 else if (i < n2 + n3)
355 check (buf1[i] == 'a', ntest);
356 else if (i < n2 + n3 + 3)
357 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
358 else if (i == n2 + n3 + 3)
359 check (buf1[i] == '\0', ntest);
360 else
361 check (buf1[i] == 'b', ntest);
363 if (errors != olderrors)
365 printf ("n1=%zu, n2=%zu, n3=%zu, buf1=%02hhx",
366 n1, n2, n3, buf1[0]);
367 for (size_t j = 1; j < sizeof (buf1); ++j)
368 printf (",%02hhx", buf1[j]);
369 putchar_unlocked ('\n');
370 break;
376 static void
377 test_strncat (void)
379 /* First test it as strcat, with big counts, then test the count
380 mechanism. */
381 it = "strncat";
382 (void) strcpy (one, "ijk");
383 check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */
384 equal (one, "ijklmn", 2); /* Basic test. */
386 (void) strcpy (one, "x");
387 (void) strncat (one, "yz", 99);
388 equal (one, "xyz", 3); /* Writeover. */
389 equal (one+4, "mn", 4); /* Wrote too much? */
391 (void) strcpy (one, "gh");
392 (void) strcpy (two, "ef");
393 /* When building with fortify enabled, GCC 6 issues an warning the fortify
394 wrapper might overflow the destination buffer. However, GCC does not
395 provide a specific flag to disable the warning (the failure is tied to
396 -Werror). So to avoid disable all errors, only enable the check for
397 GCC 7 or newer. */
398 #if __GNUC_PREREQ (7, 0)
399 (void) strncat (one, two, 99);
400 equal (one, "ghef", 5); /* Basic test encore. */
401 #else
402 equal (one, "gh", 2);
403 #endif
404 equal (two, "ef", 6); /* Stomped on source? */
406 (void) strcpy (one, "");
407 (void) strncat (one, "", 99);
408 equal (one, "", 7); /* Boundary conditions. */
409 (void) strcpy (one, "ab");
410 (void) strncat (one, "", 99);
411 equal (one, "ab", 8);
412 (void) strcpy (one, "");
413 (void) strncat (one, "cd", 99);
414 equal (one, "cd", 9);
416 (void) strcpy (one, "ab");
417 (void) strncat (one, "cdef", 2);
418 equal (one, "abcd", 10); /* Count-limited. */
420 (void) strncat (one, "gh", 0);
421 equal (one, "abcd", 11); /* Zero count. */
423 (void) strncat (one, "gh", 2);
424 equal (one, "abcdgh", 12); /* Count and length equal. */
426 (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */
427 equal (one, "abcdghij", 13);
429 int ntest = 14;
430 char buf1[80] __attribute__ ((aligned (16)));
431 char buf2[32] __attribute__ ((aligned (16)));
432 for (size_t n1 = 0; n1 < 16; ++n1)
433 for (size_t n2 = 0; n2 < 16; ++n2)
434 for (size_t n3 = 0; n3 < 32; ++n3)
435 for (size_t n4 = 0; n4 < 16; ++n4)
437 size_t olderrors = errors;
439 memset (buf1, 'b', sizeof (buf1));
441 memset (buf1 + n2, 'a', n3);
442 buf1[n2 + n3] = '\0';
443 strcpy (buf2 + n1, "123");
445 check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4)
446 == buf1 + n2, ntest);
447 if (errors == olderrors)
448 for (size_t i = 0; i < sizeof (buf1); ++i)
450 if (i < n2)
451 check (buf1[i] == 'b', ntest);
452 else if (i < n2 + n3)
453 check (buf1[i] == 'a', ntest);
454 else if (i < n2 + n3 + 3)
455 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
456 else if (i == n2 + n3 + 3)
457 check (buf1[i] == '\0', ntest);
458 else
459 check (buf1[i] == 'b', ntest);
461 if (errors != olderrors)
463 printf ("n1=%zu, n2=%zu, n3=%zu, n4=%zu, buf1=%02hhx",
464 n1, n2, n3, n4, buf1[0]);
465 for (size_t j = 1; j < sizeof (buf1); ++j)
466 printf (",%02hhx", buf1[j]);
467 putchar_unlocked ('\n');
468 break;
474 static void
475 test_strncmp (void)
477 /* First test as strcmp with big counts, then test count code. */
478 it = "strncmp";
479 check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
480 check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
481 check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */
482 check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */
483 check (strncmp ("abcd", "abc", 99) > 0, 5);
484 check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
485 check (strncmp ("abce", "abcd", 99) > 0, 7);
486 check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
487 check (strncmp ("a\203", "a\003", 2) > 0, 9);
488 check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
489 check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
490 check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
491 check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */
492 check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */
493 check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
496 static void
497 test_strncpy (void)
499 /* Testing is a bit different because of odd semantics. */
500 it = "strncpy";
501 check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */
502 equal (one, "abc", 2); /* Did the copy go right? */
504 (void) strcpy (one, "abcdefgh");
505 (void) strncpy (one, "xyz", 2);
506 equal (one, "xycdefgh", 3); /* Copy cut by count. */
508 (void) strcpy (one, "abcdefgh");
509 (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */
510 equal (one, "xyzdefgh", 4);
512 (void) strcpy (one, "abcdefgh");
513 (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */
514 equal (one, "xyz", 5);
515 equal (one+4, "efgh", 6); /* Wrote too much? */
517 (void) strcpy (one, "abcdefgh");
518 (void) strncpy (one, "xyz", 5); /* Copy includes padding. */
519 equal (one, "xyz", 7);
520 equal (one+4, "", 8);
521 equal (one+5, "fgh", 9);
523 (void) strcpy (one, "abc");
524 (void) strncpy (one, "xyz", 0); /* Zero-length copy. */
525 equal (one, "abc", 10);
527 (void) strncpy (one, "", 2); /* Zero-length source. */
528 equal (one, "", 11);
529 equal (one+1, "", 12);
530 equal (one+2, "c", 13);
532 (void) strcpy (one, "hi there");
533 (void) strncpy (two, one, 9);
534 equal (two, "hi there", 14); /* Just paranoia. */
535 equal (one, "hi there", 15); /* Stomped on source? */
538 static void
539 test_strlen (void)
541 it = "strlen";
542 check (strlen ("") == 0, 1); /* Empty. */
543 check (strlen ("a") == 1, 2); /* Single char. */
544 check (strlen ("abcd") == 4, 3); /* Multiple chars. */
546 char buf[4096];
547 int i;
548 char *p;
549 for (i=0; i < 0x100; i++)
551 p = (char *) ((uintptr_t)(buf + 0xff) & ~0xff) + i;
552 strcpy (p, "OK");
553 strcpy (p+3, "BAD/WRONG");
554 check (strlen (p) == 2, 4+i);
559 static void
560 test_strnlen (void)
562 it = "strnlen";
563 check (strnlen ("", 10) == 0, 1); /* Empty. */
564 check (strnlen ("a", 10) == 1, 2); /* Single char. */
565 check (strnlen ("abcd", 10) == 4, 3); /* Multiple chars. */
566 check (strnlen ("foo", (size_t) -1) == 3, 4); /* limits of n. */
567 check (strnlen ("abcd", 0) == 0, 5); /* Restricted. */
568 check (strnlen ("abcd", 1) == 1, 6); /* Restricted. */
569 check (strnlen ("abcd", 2) == 2, 7); /* Restricted. */
570 check (strnlen ("abcd", 3) == 3, 8); /* Restricted. */
571 check (strnlen ("abcd", 4) == 4, 9); /* Restricted. */
573 char buf[4096];
574 for (int i = 0; i < 0x100; ++i)
576 char *p = (char *) ((uintptr_t)(buf + 0xff) & ~0xff) + i;
577 strcpy (p, "OK");
578 strcpy (p + 3, "BAD/WRONG");
579 check (strnlen (p, 100) == 2, 10 + i);
583 static void
584 test_strchr (void)
586 it = "strchr";
587 check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */
588 (void) strcpy (one, "abcd");
589 check (strchr (one, 'c') == one+2, 2); /* Basic test. */
590 check (strchr (one, 'd') == one+3, 3); /* End of string. */
591 check (strchr (one, 'a') == one, 4); /* Beginning. */
592 check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
593 (void) strcpy (one, "ababa");
594 check (strchr (one, 'b') == one+1, 6); /* Finding first. */
595 (void) strcpy (one, "");
596 check (strchr (one, 'b') == NULL, 7); /* Empty string. */
597 check (strchr (one, '\0') == one, 8); /* NUL in empty string. */
599 char buf[4096];
600 int i;
601 char *p;
602 for (i=0; i < 0x100; i++)
604 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
605 strcpy (p, "OK");
606 strcpy (p+3, "BAD/WRONG");
607 check (strchr (p, '/') == NULL, 9+i);
612 static void
613 test_strchrnul (void)
615 const char *os;
616 it = "strchrnul";
617 cp = strchrnul ((os = "abcd"), 'z');
618 check (*cp == '\0', 1); /* Not found. */
619 check (cp == os + 4, 2);
620 (void) strcpy (one, "abcd");
621 check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */
622 check (strchrnul (one, 'd') == one+3, 4); /* End of string. */
623 check (strchrnul (one, 'a') == one, 5); /* Beginning. */
624 check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */
625 (void) strcpy (one, "ababa");
626 check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */
627 (void) strcpy (one, "");
628 check (strchrnul (one, 'b') == one, 8); /* Empty string. */
629 check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */
631 char buf[4096];
632 int i;
633 char *p;
634 for (i=0; i < 0x100; i++)
636 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
637 strcpy (p, "OK");
638 strcpy (p+3, "BAD/WRONG");
639 cp = strchrnul (p, '/');
640 check (*cp == '\0', 9+2*i);
641 check (cp == p+2, 10+2*i);
646 static void
647 test_rawmemchr (void)
649 it = "rawmemchr";
650 (void) strcpy (one, "abcd");
651 check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */
652 check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */
653 check (rawmemchr (one, 'a') == one, 3); /* Beginning. */
654 check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */
655 (void) strcpy (one, "ababa");
656 check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */
657 (void) strcpy (one, "");
658 check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */
660 char buf[4096];
661 int i;
662 char *p;
663 for (i=0; i < 0x100; i++)
665 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
666 strcpy (p, "OK");
667 strcpy (p+3, "BAD/WRONG");
668 check (rawmemchr (p, 'R') == p+8, 6+i);
673 static void
674 test_index (void)
676 it = "index";
677 check (index ("abcd", 'z') == NULL, 1); /* Not found. */
678 (void) strcpy (one, "abcd");
679 check (index (one, 'c') == one+2, 2); /* Basic test. */
680 check (index (one, 'd') == one+3, 3); /* End of string. */
681 check (index (one, 'a') == one, 4); /* Beginning. */
682 check (index (one, '\0') == one+4, 5); /* Finding NUL. */
683 (void) strcpy (one, "ababa");
684 check (index (one, 'b') == one+1, 6); /* Finding first. */
685 (void) strcpy (one, "");
686 check (index (one, 'b') == NULL, 7); /* Empty string. */
687 check (index (one, '\0') == one, 8); /* NUL in empty string. */
690 static void
691 test_strrchr (void)
693 it = "strrchr";
694 check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */
695 (void) strcpy (one, "abcd");
696 check (strrchr (one, 'c') == one+2, 2); /* Basic test. */
697 check (strrchr (one, 'd') == one+3, 3); /* End of string. */
698 check (strrchr (one, 'a') == one, 4); /* Beginning. */
699 check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */
700 (void) strcpy (one, "ababa");
701 check (strrchr (one, 'b') == one+3, 6); /* Finding last. */
702 (void) strcpy (one, "");
703 check (strrchr (one, 'b') == NULL, 7); /* Empty string. */
704 check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */
706 char buf[4096];
707 int i;
708 char *p;
709 for (i=0; i < 0x100; i++)
711 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
712 strcpy (p, "OK");
713 strcpy (p+3, "BAD/WRONG");
714 check (strrchr (p, '/') == NULL, 9+i);
719 static void
720 test_memrchr (void)
722 size_t l;
723 it = "memrchr";
724 check (memrchr ("abcd", 'z', 5) == NULL, 1); /* Not found. */
725 (void) strcpy (one, "abcd");
726 l = strlen (one) + 1;
727 check (memrchr (one, 'c', l) == one+2, 2); /* Basic test. */
728 check (memrchr (one, 'd', l) == one+3, 3); /* End of string. */
729 check (memrchr (one, 'a', l) == one, 4); /* Beginning. */
730 check (memrchr (one, '\0', l) == one+4, 5); /* Finding NUL. */
731 (void) strcpy (one, "ababa");
732 l = strlen (one) + 1;
733 check (memrchr (one, 'b', l) == one+3, 6); /* Finding last. */
734 (void) strcpy (one, "");
735 l = strlen (one) + 1;
736 check (memrchr (one, 'b', l) == NULL, 7); /* Empty string. */
737 check (memrchr (one, '\0', l) == one, 8); /* NUL in empty string. */
739 /* now test all possible alignment and length combinations to catch
740 bugs due to unrolled loops (assuming unrolling is limited to no
741 more than 128 byte chunks: */
743 char buf[128 + sizeof (long)];
744 long align, len, i, pos, n = 9;
746 for (align = 0; align < (long) sizeof (long); ++align) {
747 for (len = 0; len < (long) (sizeof (buf) - align); ++len) {
748 for (i = 0; i < len; ++i)
749 buf[align + i] = 'x'; /* don't depend on memset... */
751 for (pos = len - 1; pos >= 0; --pos) {
752 #if 0
753 printf("align %d, len %d, pos %d\n", align, len, pos);
754 #endif
755 check(memrchr(buf + align, 'x', len) == buf + align + pos, n++);
756 check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
757 n++);
758 buf[align + pos] = '-';
765 static void
766 test_rindex (void)
768 it = "rindex";
769 check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */
770 (void) strcpy (one, "abcd");
771 check (rindex (one, 'c') == one+2, 2); /* Basic test. */
772 check (rindex (one, 'd') == one+3, 3); /* End of string. */
773 check (rindex (one, 'a') == one, 4); /* Beginning. */
774 check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
775 (void) strcpy (one, "ababa");
776 check (rindex (one, 'b') == one+3, 6); /* Finding last. */
777 (void) strcpy (one, "");
778 check (rindex (one, 'b') == NULL, 7); /* Empty string. */
779 check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
782 static void
783 test_strpbrk (void)
785 it = "strpbrk";
786 check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
787 (void) strcpy(one, "abcd");
788 check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
789 check(strpbrk(one, "d") == one+3, 3); /* End of string. */
790 check(strpbrk(one, "a") == one, 4); /* Beginning. */
791 check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
792 check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
793 (void) strcpy(one, "abcabdea");
794 check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
795 check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
796 check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
797 (void) strcpy(one, "");
798 check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
799 (void) strcpy(one, "");
800 check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
801 (void) strcpy(one, "");
802 check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */
803 check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */
804 (void) strcpy(one, "abcabdea");
805 check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */
806 check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */
807 check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
808 check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */
811 static void
812 test_strstr (void)
814 it = "strstr";
815 check(strstr("abcd", "z") == NULL, 1); /* Not found. */
816 check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
817 (void) strcpy(one, "abcd");
818 check(strstr(one, "c") == one+2, 3); /* Basic test. */
819 check(strstr(one, "bc") == one+1, 4); /* Multichar. */
820 check(strstr(one, "d") == one+3, 5); /* End of string. */
821 check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
822 check(strstr(one, "abc") == one, 7); /* Beginning. */
823 check(strstr(one, "abcd") == one, 8); /* Exact match. */
824 check(strstr(one, "abcde") == NULL, 9); /* Too long. */
825 check(strstr(one, "de") == NULL, 10); /* Past end. */
826 check(strstr(one, "") == one, 11); /* Finding empty. */
827 (void) strcpy(one, "ababa");
828 check(strstr(one, "ba") == one+1, 12); /* Finding first. */
829 (void) strcpy(one, "");
830 check(strstr(one, "b") == NULL, 13); /* Empty string. */
831 check(strstr(one, "") == one, 14); /* Empty in empty string. */
832 (void) strcpy(one, "bcbca");
833 check(strstr(one, "bca") == one+2, 15); /* False start. */
834 (void) strcpy(one, "bbbcabbca");
835 check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
838 static void
839 test_strspn (void)
841 it = "strspn";
842 check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
843 check(strspn("abcba", "ab") == 2, 2); /* Partial. */
844 check(strspn("abc", "qx") == 0, 3); /* None. */
845 check(strspn("", "ab") == 0, 4); /* Null string. */
846 check(strspn("abc", "") == 0, 5); /* Null search list. */
849 static void
850 test_strcspn (void)
852 it = "strcspn";
853 check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
854 check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
855 check(strcspn("abc", "abc") == 0, 3); /* None. */
856 check(strcspn("", "ab") == 0, 4); /* Null string. */
857 check(strcspn("abc", "") == 3, 5); /* Null search list. */
860 static void
861 test_strtok (void)
863 it = "strtok";
864 (void) strcpy(one, "first, second, third");
865 equal(strtok(one, ", "), "first", 1); /* Basic test. */
866 equal(one, "first", 2);
867 equal(strtok((char *)NULL, ", "), "second", 3);
868 equal(strtok((char *)NULL, ", "), "third", 4);
869 check(strtok((char *)NULL, ", ") == NULL, 5);
870 (void) strcpy(one, ", first, ");
871 equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
872 check(strtok((char *)NULL, ", ") == NULL, 7);
873 (void) strcpy(one, "1a, 1b; 2a, 2b");
874 equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
875 equal(strtok((char *)NULL, "; "), "1b", 9);
876 equal(strtok((char *)NULL, ", "), "2a", 10);
877 (void) strcpy(two, "x-y");
878 equal(strtok(two, "-"), "x", 11); /* New string before done. */
879 equal(strtok((char *)NULL, "-"), "y", 12);
880 check(strtok((char *)NULL, "-") == NULL, 13);
881 (void) strcpy(one, "a,b, c,, ,d");
882 equal(strtok(one, ", "), "a", 14); /* Different separators. */
883 equal(strtok((char *)NULL, ", "), "b", 15);
884 equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
885 equal(strtok((char *)NULL, " ,"), "d", 17);
886 check(strtok((char *)NULL, ", ") == NULL, 18);
887 check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
888 (void) strcpy(one, ", ");
889 check(strtok(one, ", ") == NULL, 20); /* No tokens. */
890 (void) strcpy(one, "");
891 check(strtok(one, ", ") == NULL, 21); /* Empty string. */
892 (void) strcpy(one, "abc");
893 equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
894 check(strtok((char *)NULL, ", ") == NULL, 23);
895 (void) strcpy(one, "abc");
896 equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
897 check(strtok((char *)NULL, "") == NULL, 25);
898 (void) strcpy(one, "abcdefgh");
899 (void) strcpy(one, "a,b,c");
900 equal(strtok(one, ","), "a", 26); /* Basics again... */
901 equal(strtok((char *)NULL, ","), "b", 27);
902 equal(strtok((char *)NULL, ","), "c", 28);
903 check(strtok((char *)NULL, ",") == NULL, 29);
904 equal(one+6, "gh", 30); /* Stomped past end? */
905 equal(one, "a", 31); /* Stomped old tokens? */
906 equal(one+2, "b", 32);
907 equal(one+4, "c", 33);
910 static void
911 test_strtok_r (void)
913 it = "strtok_r";
914 (void) strcpy(one, "first, second, third");
915 cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */
916 equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
917 equal(one, "first", 2);
918 equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
919 equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
920 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
921 (void) strcpy(one, ", first, ");
922 cp = NULL;
923 equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
924 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
925 (void) strcpy(one, "1a, 1b; 2a, 2b");
926 cp = NULL;
927 equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
928 equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
929 equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
930 (void) strcpy(two, "x-y");
931 cp = NULL;
932 equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
933 equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
934 check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
935 (void) strcpy(one, "a,b, c,, ,d");
936 cp = NULL;
937 equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
938 equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
939 equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
940 equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
941 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
942 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
943 (void) strcpy(one, ", ");
944 cp = NULL;
945 check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
946 (void) strcpy(one, "");
947 cp = NULL;
948 check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
949 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
950 (void) strcpy(one, "abc");
951 cp = NULL;
952 equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */
953 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
954 (void) strcpy(one, "abc");
955 cp = NULL;
956 equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */
957 check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
958 (void) strcpy(one, "abcdefgh");
959 (void) strcpy(one, "a,b,c");
960 cp = NULL;
961 equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */
962 equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
963 equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
964 check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
965 equal(one+6, "gh", 31); /* Stomped past end? */
966 equal(one, "a", 32); /* Stomped old tokens? */
967 equal(one+2, "b", 33);
968 equal(one+4, "c", 34);
969 strcpy (one, ":::");
970 cp = NULL;
971 check (strtok_r (one, ":", &cp) == NULL, 35); /* Must store pointer in cp. */
972 check (strtok_r (NULL, ":", &cp) == NULL, 36);
975 static void
976 test_strsep (void)
978 char *ptr;
979 it = "strsep";
980 cp = strcpy(one, "first, second, third");
981 equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
982 equal(one, "first", 2);
983 equal(strsep(&cp, ", "), "", 3);
984 equal(strsep(&cp, ", "), "second", 4);
985 equal(strsep(&cp, ", "), "", 5);
986 equal(strsep(&cp, ", "), "third", 6);
987 check(strsep(&cp, ", ") == NULL, 7);
988 cp = strcpy(one, ", first, ");
989 equal(strsep(&cp, ", "), "", 8);
990 equal(strsep(&cp, ", "), "", 9);
991 equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
992 equal(strsep(&cp, ", "), "", 11);
993 equal(strsep(&cp, ", "), "", 12);
994 check(strsep(&cp, ", ") == NULL, 13);
995 cp = strcpy(one, "1a, 1b; 2a, 2b");
996 equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */
997 equal(strsep(&cp, ", "), "", 15);
998 equal(strsep(&cp, "; "), "1b", 16);
999 equal(strsep(&cp, ", "), "", 17);
1000 equal(strsep(&cp, ", "), "2a", 18);
1001 cp = strcpy(two, "x-y");
1002 equal(strsep(&cp, "-"), "x", 19); /* New string before done. */
1003 equal(strsep(&cp, "-"), "y", 20);
1004 check(strsep(&cp, "-") == NULL, 21);
1005 cp = strcpy(one, "a,b, c,, ,d ");
1006 equal(strsep(&cp, ", "), "a", 22); /* Different separators. */
1007 equal(strsep(&cp, ", "), "b", 23);
1008 equal(strsep(&cp, " ,"), "", 24);
1009 equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */
1010 equal(strsep(&cp, " ,"), "", 26);
1011 equal(strsep(&cp, " ,"), "", 27);
1012 equal(strsep(&cp, " ,"), "", 28);
1013 equal(strsep(&cp, " ,"), "d", 29);
1014 equal(strsep(&cp, " ,"), "", 30);
1015 check(strsep(&cp, ", ") == NULL, 31);
1016 check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
1017 cp = strcpy(one, ", ");
1018 equal(strsep(&cp, ", "), "", 33);
1019 equal(strsep(&cp, ", "), "", 34);
1020 equal(strsep(&cp, ", "), "", 35);
1021 check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
1022 cp = strcpy(one, "");
1023 equal(strsep(&cp, ", "), "", 37);
1024 check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
1025 cp = strcpy(one, "abc");
1026 equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */
1027 check(strsep(&cp, ", ") == NULL, 40);
1028 cp = strcpy(one, "abc");
1029 equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */
1030 check(strsep(&cp, "") == NULL, 42);
1031 (void) strcpy(one, "abcdefgh");
1032 cp = strcpy(one, "a,b,c");
1033 equal(strsep(&cp, ","), "a", 43); /* Basics again... */
1034 equal(strsep(&cp, ","), "b", 44);
1035 equal(strsep(&cp, ","), "c", 45);
1036 check(strsep(&cp, ",") == NULL, 46);
1037 equal(one+6, "gh", 47); /* Stomped past end? */
1038 equal(one, "a", 48); /* Stomped old tokens? */
1039 equal(one+2, "b", 49);
1040 equal(one+4, "c", 50);
1043 char text[] = "This,is,a,test";
1044 char *list = strdupa (text);
1045 equal (strsep (&list, ","), "This", 51);
1046 equal (strsep (&list, ","), "is", 52);
1047 equal (strsep (&list, ","), "a", 53);
1048 equal (strsep (&list, ","), "test", 54);
1049 check (strsep (&list, ",") == NULL, 55);
1052 cp = strcpy(one, "a,b, c,, ,d,");
1053 equal(strsep(&cp, ","), "a", 56); /* Different separators. */
1054 equal(strsep(&cp, ","), "b", 57);
1055 equal(strsep(&cp, ","), " c", 58); /* Permute list too. */
1056 equal(strsep(&cp, ","), "", 59);
1057 equal(strsep(&cp, ","), " ", 60);
1058 equal(strsep(&cp, ","), "d", 61);
1059 equal(strsep(&cp, ","), "", 62);
1060 check(strsep(&cp, ",") == NULL, 63);
1061 check(strsep(&cp, ",") == NULL, 64); /* Persistence. */
1063 cp = strcpy(one, "a,b, c,, ,d,");
1064 equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */
1065 equal(strsep(&cp, "x,y"), "b", 66);
1066 equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */
1067 equal(strsep(&cp, "xy,"), "", 68);
1068 equal(strsep(&cp, "x,y"), " ", 69);
1069 equal(strsep(&cp, ",xy"), "d", 70);
1070 equal(strsep(&cp, "xy,"), "", 71);
1071 check(strsep(&cp, "x,y") == NULL, 72);
1072 check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */
1074 cp = strcpy(one, "ABC");
1075 one[4] = ':';
1076 equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */
1077 ptr = strsep(&cp, ":");
1078 equal(ptr, "", 75);
1079 check(ptr == one + 3, 76);
1080 check(cp == NULL, 77);
1082 cp = strcpy(one, "ABC");
1083 one[4] = ':';
1084 equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */
1085 ptr = strsep(&cp, ":.");
1086 equal(ptr, "", 79);
1087 check(ptr == one + 3, 80);
1089 cp = strcpy(one, "ABC"); /* No token in string. */
1090 equal(strsep(&cp, ","), "ABC", 81);
1091 check(cp == NULL, 82);
1093 *one = '\0'; /* Empty string. */
1094 cp = one;
1095 ptr = strsep(&cp, ",");
1096 equal(ptr, "", 83);
1097 check(ptr == one, 84);
1098 check(cp == NULL, 85);
1100 *one = '\0'; /* Empty string and no token. */
1101 cp = one;
1102 ptr = strsep(&cp, "");
1103 equal(ptr, "", 86);
1104 check(ptr == one , 87);
1105 check(cp == NULL, 88);
1108 static void
1109 test_memcmp (void)
1111 int cnt = 1;
1112 char one[21];
1113 char two[21];
1115 it = "memcmp";
1116 check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */
1117 check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */
1118 check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */
1119 check(memcmp("abcf", "abcd", 4) > 0, cnt++);
1120 check(memcmp("alph", "cold", 4) < 0, cnt++);
1121 check(memcmp("a\203", "a\003", 2) > 0, cnt++);
1122 check(memcmp("a\003", "a\203", 2) < 0, cnt++);
1123 check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
1124 check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
1125 check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
1126 check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */
1127 check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */
1128 /* Comparisons with shifting 4-byte boundaries. */
1129 for (int i = 0; i < 4; ++i)
1131 char *a = one + i;
1132 char *b = two + i;
1133 memcpy(a, "--------11112222", 16);
1134 memcpy(b, "--------33334444", 16);
1135 check(memcmp(b, a, 16) > 0, cnt++);
1136 check(memcmp(a, b, 16) < 0, cnt++);
1140 static void
1141 test_memchr (void)
1143 it = "memchr";
1144 check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
1145 (void) strcpy(one, "abcd");
1146 check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
1147 check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
1148 check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
1149 check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
1150 check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
1151 (void) strcpy(one, "ababa");
1152 check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
1153 check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
1154 check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
1155 (void) strcpy(one, "a\203b");
1156 check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
1158 /* now test all possible alignment and length combinations to catch
1159 bugs due to unrolled loops (assuming unrolling is limited to no
1160 more than 128 byte chunks: */
1162 char buf[128 + sizeof (long)];
1163 long align, len, i, pos;
1165 for (align = 0; align < (long) sizeof (long); ++align) {
1166 for (len = 0; len < (long) (sizeof (buf) - align); ++len) {
1167 for (i = 0; i < len; ++i) {
1168 buf[align + i] = 'x'; /* don't depend on memset... */
1170 for (pos = 0; pos < len; ++pos) {
1171 #if 0
1172 printf("align %d, len %d, pos %d\n", align, len, pos);
1173 #endif
1174 check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
1175 check(memchr(buf + align, 'x', pos) == NULL, 11);
1176 buf[align + pos] = '-';
1183 static void
1184 test_memcpy (void)
1186 int i;
1187 it = "memcpy";
1188 check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
1189 equal(one, "abc", 2); /* Did the copy go right? */
1191 (void) strcpy(one, "abcdefgh");
1192 (void) memcpy(one+1, "xyz", 2);
1193 equal(one, "axydefgh", 3); /* Basic test. */
1195 (void) strcpy(one, "abc");
1196 (void) memcpy(one, "xyz", 0);
1197 equal(one, "abc", 4); /* Zero-length copy. */
1199 (void) strcpy(one, "hi there");
1200 (void) strcpy(two, "foo");
1201 (void) memcpy(two, one, 9);
1202 equal(two, "hi there", 5); /* Just paranoia. */
1203 equal(one, "hi there", 6); /* Stomped on source? */
1205 for (i = 0; i < 16; i++)
1207 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1208 strcpy (one, x);
1209 check (memcpy (one + i, "hi there", 9) == one + i,
1210 7 + (i * 6)); /* Unaligned destination. */
1211 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1212 equal (one + i, "hi there", 9 + (i * 6));
1213 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1214 check (memcpy (two, one + i, 9) == two,
1215 11 + (i * 6)); /* Unaligned source. */
1216 equal (two, "hi there", 12 + (i * 6));
1220 static void
1221 test_mempcpy (void)
1223 int i;
1224 it = "mempcpy";
1225 check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */
1226 equal(one, "abc", 2); /* Did the copy go right? */
1228 (void) strcpy(one, "abcdefgh");
1229 (void) mempcpy(one+1, "xyz", 2);
1230 equal(one, "axydefgh", 3); /* Basic test. */
1232 (void) strcpy(one, "abc");
1233 (void) mempcpy(one, "xyz", 0);
1234 equal(one, "abc", 4); /* Zero-length copy. */
1236 (void) strcpy(one, "hi there");
1237 (void) strcpy(two, "foo");
1238 (void) mempcpy(two, one, 9);
1239 equal(two, "hi there", 5); /* Just paranoia. */
1240 equal(one, "hi there", 6); /* Stomped on source? */
1242 for (i = 0; i < 16; i++)
1244 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1245 strcpy (one, x);
1246 check (mempcpy (one + i, "hi there", 9) == one + i + 9,
1247 7 + (i * 6)); /* Unaligned destination. */
1248 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1249 equal (one + i, "hi there", 9 + (i * 6));
1250 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1251 check (mempcpy (two, one + i, 9) == two + 9,
1252 11 + (i * 6)); /* Unaligned source. */
1253 equal (two, "hi there", 12 + (i * 6));
1257 static void
1258 test_memmove (void)
1260 it = "memmove";
1261 check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
1262 equal(one, "abc", 2); /* Did the copy go right? */
1264 (void) strcpy(one, "abcdefgh");
1265 (void) memmove(one+1, "xyz", 2);
1266 equal(one, "axydefgh", 3); /* Basic test. */
1268 (void) strcpy(one, "abc");
1269 (void) memmove(one, "xyz", 0);
1270 equal(one, "abc", 4); /* Zero-length copy. */
1272 (void) strcpy(one, "hi there");
1273 (void) strcpy(two, "foo");
1274 (void) memmove(two, one, 9);
1275 equal(two, "hi there", 5); /* Just paranoia. */
1276 equal(one, "hi there", 6); /* Stomped on source? */
1278 (void) strcpy(one, "abcdefgh");
1279 (void) memmove(one+1, one, 9);
1280 equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
1282 (void) strcpy(one, "abcdefgh");
1283 (void) memmove(one+1, one+2, 7);
1284 equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
1286 (void) strcpy(one, "abcdefgh");
1287 (void) memmove(one, one, 9);
1288 equal(one, "abcdefgh", 9); /* 100% overlap. */
1291 static void
1292 test_memccpy (void)
1294 /* First test like memcpy, then the search part The SVID, the only
1295 place where memccpy is mentioned, says overlap might fail, so we
1296 don't try it. Besides, it's hard to see the rationale for a
1297 non-left-to-right memccpy. */
1298 it = "memccpy";
1299 check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
1300 equal(one, "abc", 2); /* Did the copy go right? */
1302 (void) strcpy(one, "abcdefgh");
1303 (void) memccpy(one+1, "xyz", 'q', 2);
1304 equal(one, "axydefgh", 3); /* Basic test. */
1306 (void) strcpy(one, "abc");
1307 (void) memccpy(one, "xyz", 'q', 0);
1308 equal(one, "abc", 4); /* Zero-length copy. */
1310 (void) strcpy(one, "hi there");
1311 (void) strcpy(two, "foo");
1312 (void) memccpy(two, one, 'q', 9);
1313 equal(two, "hi there", 5); /* Just paranoia. */
1314 equal(one, "hi there", 6); /* Stomped on source? */
1316 (void) strcpy(one, "abcdefgh");
1317 (void) strcpy(two, "horsefeathers");
1318 check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
1319 equal(one, "abcdefgh", 8); /* Source intact? */
1320 equal(two, "abcdefeathers", 9); /* Copy correct? */
1322 (void) strcpy(one, "abcd");
1323 (void) strcpy(two, "bumblebee");
1324 check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
1325 equal(two, "aumblebee", 11);
1326 check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
1327 equal(two, "abcdlebee", 13);
1328 (void) strcpy(one, "xyz");
1329 check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
1330 equal(two, "xbcdlebee", 15);
1333 static void
1334 test_memset (void)
1336 int i;
1338 it = "memset";
1339 (void) strcpy(one, "abcdefgh");
1340 check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
1341 equal(one, "axxxefgh", 2); /* Basic test. */
1343 (void) memset(one+2, 'y', 0);
1344 equal(one, "axxxefgh", 3); /* Zero-length set. */
1346 (void) memset(one+5, 0, 1);
1347 equal(one, "axxxe", 4); /* Zero fill. */
1348 equal(one+6, "gh", 5); /* And the leftover. */
1350 (void) memset(one+2, 010045, 1);
1351 equal(one, "ax\045xe", 6); /* Unsigned char convert. */
1353 /* Non-8bit fill character. */
1354 memset (one, 0x101, sizeof (one));
1355 for (i = 0; i < (int) sizeof (one); ++i)
1356 check (one[i] == '\01', 7);
1358 /* Test for more complex versions of memset, for all alignments and
1359 lengths up to 256. This test takes a little while, perhaps it should
1360 be made weaker? */
1362 char data[512];
1363 int j;
1364 int k;
1365 int c;
1367 for (i = 0; i < 512; i++)
1368 data[i] = 'x';
1369 for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
1370 memset(,'y',) */
1371 for (j = 0; j < 256; j++)
1372 for (i = 0; i < 256; i++)
1374 memset (data + i, c, j);
1375 for (k = 0; k < i; k++)
1376 if (data[k] != 'x')
1377 goto fail;
1378 for (k = i; k < i+j; k++)
1380 if (data[k] != c)
1381 goto fail;
1382 data[k] = 'x';
1384 for (k = i+j; k < 512; k++)
1385 if (data[k] != 'x')
1386 goto fail;
1387 continue;
1389 fail:
1390 check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1395 static void
1396 test_bcopy (void)
1398 /* Much like memcpy. Berklix manual is silent about overlap, so
1399 don't test it. */
1400 it = "bcopy";
1401 (void) bcopy("abc", one, 4);
1402 equal(one, "abc", 1); /* Simple copy. */
1404 (void) strcpy(one, "abcdefgh");
1405 (void) bcopy("xyz", one+1, 2);
1406 equal(one, "axydefgh", 2); /* Basic test. */
1408 (void) strcpy(one, "abc");
1409 (void) bcopy("xyz", one, 0);
1410 equal(one, "abc", 3); /* Zero-length copy. */
1412 (void) strcpy(one, "hi there");
1413 (void) strcpy(two, "foo");
1414 (void) bcopy(one, two, 9);
1415 equal(two, "hi there", 4); /* Just paranoia. */
1416 equal(one, "hi there", 5); /* Stomped on source? */
1419 static void
1420 test_bzero (void)
1422 it = "bzero";
1423 (void) strcpy(one, "abcdef");
1424 bzero(one+2, 2);
1425 equal(one, "ab", 1); /* Basic test. */
1426 equal(one+3, "", 2);
1427 equal(one+4, "ef", 3);
1429 (void) strcpy(one, "abcdef");
1430 bzero(one+2, 0);
1431 equal(one, "abcdef", 4); /* Zero-length copy. */
1434 static void
1435 test_strndup (void)
1437 char *p, *q;
1438 it = "strndup";
1439 p = strndup("abcdef", 12);
1440 check(p != NULL, 1);
1441 if (p != NULL)
1443 equal(p, "abcdef", 2);
1444 q = strndup(p + 1, 2);
1445 check(q != NULL, 3);
1446 if (q != NULL)
1447 equal(q, "bc", 4);
1448 free (q);
1450 free (p);
1451 p = strndup("abc def", 3);
1452 check(p != NULL, 5);
1453 if (p != NULL)
1454 equal(p, "abc", 6);
1455 free (p);
1458 static void
1459 test_bcmp (void)
1461 it = "bcmp";
1462 check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
1463 check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1464 check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1465 check(bcmp("abce", "abcd", 4) != 0, 4);
1466 check(bcmp("alph", "beta", 4) != 0, 5);
1467 check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
1468 check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1471 static void
1472 test_memcmpeq (void)
1474 it = "__memcmpeq";
1475 check (__memcmpeq ("a", "a", 1) == 0, 1); /* Identity. */
1476 check (__memcmpeq ("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1477 check (__memcmpeq ("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1478 check (__memcmpeq ("abce", "abcd", 4) != 0, 4);
1479 check (__memcmpeq ("alph", "beta", 4) != 0, 5);
1480 check (__memcmpeq ("abce", "abcd", 3) == 0, 6); /* Count limited. */
1481 check (__memcmpeq ("abc", "def", 0) == 0, 8); /* Zero count. */
1484 static void
1485 test_strerror (void)
1487 it = "strerror";
1488 check(strerror(EDOM) != 0, 1);
1489 check(strerror(ERANGE) != 0, 2);
1490 check(strerror(ENOENT) != 0, 3);
1493 static void
1494 test_strcasecmp (void)
1496 it = "strcasecmp";
1497 /* Note that the locale is "C". */
1498 check(strcasecmp("a", "a") == 0, 1);
1499 check(strcasecmp("a", "A") == 0, 2);
1500 check(strcasecmp("A", "a") == 0, 3);
1501 check(strcasecmp("a", "b") < 0, 4);
1502 check(strcasecmp("c", "b") > 0, 5);
1503 check(strcasecmp("abc", "AbC") == 0, 6);
1504 check(strcasecmp("0123456789", "0123456789") == 0, 7);
1505 check(strcasecmp("", "0123456789") < 0, 8);
1506 check(strcasecmp("AbC", "") > 0, 9);
1507 check(strcasecmp("AbC", "A") > 0, 10);
1508 check(strcasecmp("AbC", "Ab") > 0, 11);
1509 check(strcasecmp("AbC", "ab") > 0, 12);
1512 static void
1513 test_strncasecmp (void)
1515 it = "strncasecmp";
1516 /* Note that the locale is "C". */
1517 check(strncasecmp("a", "a", 5) == 0, 1);
1518 check(strncasecmp("a", "A", 5) == 0, 2);
1519 check(strncasecmp("A", "a", 5) == 0, 3);
1520 check(strncasecmp("a", "b", 5) < 0, 4);
1521 check(strncasecmp("c", "b", 5) > 0, 5);
1522 check(strncasecmp("abc", "AbC", 5) == 0, 6);
1523 check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
1524 check(strncasecmp("", "0123456789", 10) < 0, 8);
1525 check(strncasecmp("AbC", "", 5) > 0, 9);
1526 check(strncasecmp("AbC", "A", 5) > 0, 10);
1527 check(strncasecmp("AbC", "Ab", 5) > 0, 11);
1528 check(strncasecmp("AbC", "ab", 5) > 0, 12);
1529 check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
1530 check(strncasecmp("AbC", "abc", 1) == 0, 14);
1531 check(strncasecmp("AbC", "abc", 2) == 0, 15);
1532 check(strncasecmp("AbC", "abc", 3) == 0, 16);
1533 check(strncasecmp("AbC", "abcd", 3) == 0, 17);
1534 check(strncasecmp("AbC", "abcd", 4) < 0, 18);
1535 check(strncasecmp("ADC", "abcd", 1) == 0, 19);
1536 check(strncasecmp("ADC", "abcd", 2) > 0, 20);
1540 main (void)
1542 int status;
1544 /* Test strcmp first because we use it to test other things. */
1545 test_strcmp ();
1547 /* Test strcpy next because we need it to set up other tests. */
1548 test_strcpy ();
1550 /* A closely related function is stpcpy. */
1551 test_stpcpy ();
1553 /* stpncpy. */
1554 test_stpncpy ();
1556 /* strcat. */
1557 test_strcat ();
1559 /* strncat. */
1560 test_strncat ();
1562 /* strncmp. */
1563 test_strncmp ();
1565 /* strncpy. */
1566 test_strncpy ();
1568 /* strlen. */
1569 test_strlen ();
1571 /* strnlen. */
1572 test_strnlen ();
1574 /* strchr. */
1575 test_strchr ();
1577 /* strchrnul. */
1578 test_strchrnul ();
1580 /* rawmemchr. */
1581 test_rawmemchr ();
1583 /* index - just like strchr. */
1584 test_index ();
1586 /* strrchr. */
1587 test_strrchr ();
1589 /* memrchr. */
1590 test_memrchr ();
1592 /* rindex - just like strrchr. */
1593 test_rindex ();
1595 /* strpbrk - somewhat like strchr. */
1596 test_strpbrk ();
1598 /* strstr - somewhat like strchr. */
1599 test_strstr ();
1601 /* strspn. */
1602 test_strspn ();
1604 /* strcspn. */
1605 test_strcspn ();
1607 /* strtok - the hard one. */
1608 test_strtok ();
1610 /* strtok_r. */
1611 test_strtok_r ();
1613 /* strsep. */
1614 test_strsep ();
1616 /* memcmp. */
1617 test_memcmp ();
1619 /* memchr. */
1620 test_memchr ();
1622 /* memcpy - need not work for overlap. */
1623 test_memcpy ();
1625 /* memmove - must work on overlap. */
1626 test_memmove ();
1628 /* mempcpy */
1629 test_mempcpy ();
1631 /* memccpy. */
1632 test_memccpy ();
1634 /* memset. */
1635 test_memset ();
1637 /* bcopy. */
1638 test_bcopy ();
1640 /* bzero. */
1641 test_bzero ();
1643 /* bcmp - somewhat like memcmp. */
1644 test_bcmp ();
1646 /* __memcmpeq - somewhat like memcmp. */
1647 test_memcmpeq ();
1649 /* strndup. */
1650 test_strndup ();
1652 /* strerror - VERY system-dependent. */
1653 test_strerror ();
1655 /* strcasecmp. Without locale dependencies. */
1656 test_strcasecmp ();
1658 /* strncasecmp. Without locale dependencies. */
1659 test_strncasecmp ();
1661 if (errors == 0)
1663 status = EXIT_SUCCESS;
1664 puts("No errors.");
1666 else
1668 status = EXIT_FAILURE;
1669 printf("%zd errors.\n", errors);
1672 return status;