i386: Remove memset_chk-nonshared.S
[glibc.git] / string / tester.c
blobda42c721418dd2affe38dfea3b389e1c40d06321
1 /* Tester for string functions.
2 Copyright (C) 1995-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/>. */
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 #include <errno.h>
38 #include <stdint.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <strings.h>
43 #include <fcntl.h>
45 /* This file tests a range of corner cases of string functions,
46 including cases where truncation occurs or where sizes specified
47 are larger than the actual buffers, which result in various
48 warnings. */
49 DIAG_IGNORE_NEEDS_COMMENT (8, "-Warray-bounds");
50 DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Wmemset-transposed-args");
51 #if __GNUC_PREREQ (7, 0)
52 DIAG_IGNORE_NEEDS_COMMENT (9, "-Wrestrict");
53 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
54 #endif
55 #if __GNUC_PREREQ (11, 0)
56 DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overread");
57 #endif
60 #define STREQ(a, b) (strcmp((a), (b)) == 0)
62 const char *it = "<UNSET>"; /* Routine name for message routines. */
63 size_t errors = 0;
65 /* Complain if condition is not true. */
66 static void
67 check (int thing, int number)
69 if (!thing)
71 printf ("%s flunked test %d\n", it, number);
72 ++errors;
76 /* Complain if first two args don't strcmp as equal. */
77 static void
78 equal (const char *a, const char *b, int number)
80 check (a != NULL && b != NULL && STREQ (a, b), number);
83 char one[50];
84 char two[50];
85 char *cp;
87 static void
88 test_strcmp (void)
90 it = "strcmp";
91 check (strcmp ("", "") == 0, 1); /* Trivial case. */
92 check (strcmp ("a", "a") == 0, 2); /* Identity. */
93 check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */
94 check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */
95 check (strcmp ("abcd", "abc") > 0, 5);
96 check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */
97 check (strcmp ("abce", "abcd") > 0, 7);
98 check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */
99 check (strcmp ("a\203", "a\003") > 0, 9);
102 char buf1[0x40], buf2[0x40];
103 int i, j;
104 for (i=0; i < 0x10; i++)
105 for (j = 0; j < 0x10; j++)
107 int k;
108 for (k = 0; k < 0x3f; k++)
110 buf1[k] = '0' ^ (k & 4);
111 buf2[k] = '4' ^ (k & 4);
113 buf1[i] = buf1[0x3f] = 0;
114 buf2[j] = buf2[0x3f] = 0;
115 for (k = 0; k < 0xf; k++)
117 int cnum = 0x10+0x10*k+0x100*j+0x1000*i;
118 check (strcmp (buf1+i,buf2+j) == 0, cnum);
119 buf1[i+k] = 'A' + i + k;
120 buf1[i+k+1] = 0;
121 check (strcmp (buf1+i,buf2+j) > 0, cnum+1);
122 check (strcmp (buf2+j,buf1+i) < 0, cnum+2);
123 buf2[j+k] = 'B' + i + k;
124 buf2[j+k+1] = 0;
125 check (strcmp (buf1+i,buf2+j) < 0, cnum+3);
126 check (strcmp (buf2+j,buf1+i) > 0, cnum+4);
127 buf2[j+k] = 'A' + i + k;
128 buf1[i] = 'A' + i + 0x80;
129 check (strcmp (buf1+i,buf2+j) > 0, cnum+5);
130 check (strcmp (buf2+j,buf1+i) < 0, cnum+6);
131 buf1[i] = 'A' + i;
137 #define SIMPLE_COPY(fn, n, str, ntest) \
138 do { \
139 int __n; \
140 char *cp; \
141 for (__n = 0; __n < (int) sizeof (one); ++__n) \
142 one[__n] = 'Z'; \
143 fn (one, str); \
144 for (cp = one, __n = 0; __n < n; ++__n, ++cp) \
145 check (*cp == '0' + (n % 10), ntest); \
146 check (*cp == '\0', ntest); \
147 } while (0)
149 static void
150 test_strcpy (void)
152 int i;
153 it = "strcpy";
154 check (strcpy (one, "abcd") == one, 1); /* Returned value. */
155 equal (one, "abcd", 2); /* Basic test. */
157 (void) strcpy (one, "x");
158 equal (one, "x", 3); /* Writeover. */
159 equal (one+2, "cd", 4); /* Wrote too much? */
161 (void) strcpy (two, "hi there");
162 (void) strcpy (one, two);
163 equal (one, "hi there", 5); /* Basic test encore. */
164 equal (two, "hi there", 6); /* Stomped on source? */
166 (void) strcpy (one, "");
167 equal (one, "", 7); /* Boundary condition. */
169 for (i = 0; i < 16; i++)
171 (void) strcpy (one + i, "hi there"); /* Unaligned destination. */
172 equal (one + i, "hi there", 8 + (i * 2));
173 (void) strcpy (two, one + i); /* Unaligned source. */
174 equal (two, "hi there", 9 + (i * 2));
177 SIMPLE_COPY(strcpy, 0, "", 41);
178 SIMPLE_COPY(strcpy, 1, "1", 42);
179 SIMPLE_COPY(strcpy, 2, "22", 43);
180 SIMPLE_COPY(strcpy, 3, "333", 44);
181 SIMPLE_COPY(strcpy, 4, "4444", 45);
182 SIMPLE_COPY(strcpy, 5, "55555", 46);
183 SIMPLE_COPY(strcpy, 6, "666666", 47);
184 SIMPLE_COPY(strcpy, 7, "7777777", 48);
185 SIMPLE_COPY(strcpy, 8, "88888888", 49);
186 SIMPLE_COPY(strcpy, 9, "999999999", 50);
187 SIMPLE_COPY(strcpy, 10, "0000000000", 51);
188 SIMPLE_COPY(strcpy, 11, "11111111111", 52);
189 SIMPLE_COPY(strcpy, 12, "222222222222", 53);
190 SIMPLE_COPY(strcpy, 13, "3333333333333", 54);
191 SIMPLE_COPY(strcpy, 14, "44444444444444", 55);
192 SIMPLE_COPY(strcpy, 15, "555555555555555", 56);
193 SIMPLE_COPY(strcpy, 16, "6666666666666666", 57);
195 /* Simple test using implicitly coerced `void *' arguments. */
196 const void *src = "frobozz";
197 void *dst = one;
198 check (strcpy (dst, src) == dst, 1);
199 equal (dst, "frobozz", 2);
202 static void
203 test_stpcpy (void)
205 it = "stpcpy";
206 check ((stpcpy (one, "a") - one) == 1, 1);
207 equal (one, "a", 2);
209 check ((stpcpy (one, "ab") - one) == 2, 3);
210 equal (one, "ab", 4);
212 check ((stpcpy (one, "abc") - one) == 3, 5);
213 equal (one, "abc", 6);
215 check ((stpcpy (one, "abcd") - one) == 4, 7);
216 equal (one, "abcd", 8);
218 check ((stpcpy (one, "abcde") - one) == 5, 9);
219 equal (one, "abcde", 10);
221 check ((stpcpy (one, "abcdef") - one) == 6, 11);
222 equal (one, "abcdef", 12);
224 check ((stpcpy (one, "abcdefg") - one) == 7, 13);
225 equal (one, "abcdefg", 14);
227 check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
228 equal (one, "abcdefgh", 16);
230 check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
231 equal (one, "abcdefghi", 18);
233 check ((stpcpy (one, "x") - one) == 1, 19);
234 equal (one, "x", 20); /* Writeover. */
235 equal (one+2, "cdefghi", 21); /* Wrote too much? */
237 check ((stpcpy (one, "xx") - one) == 2, 22);
238 equal (one, "xx", 23); /* Writeover. */
239 equal (one+3, "defghi", 24); /* Wrote too much? */
241 check ((stpcpy (one, "xxx") - one) == 3, 25);
242 equal (one, "xxx", 26); /* Writeover. */
243 equal (one+4, "efghi", 27); /* Wrote too much? */
245 check ((stpcpy (one, "xxxx") - one) == 4, 28);
246 equal (one, "xxxx", 29); /* Writeover. */
247 equal (one+5, "fghi", 30); /* Wrote too much? */
249 check ((stpcpy (one, "xxxxx") - one) == 5, 31);
250 equal (one, "xxxxx", 32); /* Writeover. */
251 equal (one+6, "ghi", 33); /* Wrote too much? */
253 check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
254 equal (one, "xxxxxx", 35); /* Writeover. */
255 equal (one+7, "hi", 36); /* Wrote too much? */
257 check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
258 equal (one, "xxxxxxx", 38); /* Writeover. */
259 equal (one+8, "i", 39); /* Wrote too much? */
261 check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
262 equal (one, "abc", 41);
263 equal (one + 4, "xxx", 42);
265 SIMPLE_COPY(stpcpy, 0, "", 43);
266 SIMPLE_COPY(stpcpy, 1, "1", 44);
267 SIMPLE_COPY(stpcpy, 2, "22", 45);
268 SIMPLE_COPY(stpcpy, 3, "333", 46);
269 SIMPLE_COPY(stpcpy, 4, "4444", 47);
270 SIMPLE_COPY(stpcpy, 5, "55555", 48);
271 SIMPLE_COPY(stpcpy, 6, "666666", 49);
272 SIMPLE_COPY(stpcpy, 7, "7777777", 50);
273 SIMPLE_COPY(stpcpy, 8, "88888888", 51);
274 SIMPLE_COPY(stpcpy, 9, "999999999", 52);
275 SIMPLE_COPY(stpcpy, 10, "0000000000", 53);
276 SIMPLE_COPY(stpcpy, 11, "11111111111", 54);
277 SIMPLE_COPY(stpcpy, 12, "222222222222", 55);
278 SIMPLE_COPY(stpcpy, 13, "3333333333333", 56);
279 SIMPLE_COPY(stpcpy, 14, "44444444444444", 57);
280 SIMPLE_COPY(stpcpy, 15, "555555555555555", 58);
281 SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59);
284 static void
285 test_stpncpy (void)
287 it = "stpncpy";
288 memset (one, 'x', sizeof (one));
289 check (stpncpy (one, "abc", 2) == one + 2, 1);
290 check (stpncpy (one, "abc", 3) == one + 3, 2);
291 check (stpncpy (one, "abc", 4) == one + 3, 3);
292 check (one[3] == '\0' && one[4] == 'x', 4);
293 check (stpncpy (one, "abcd", 5) == one + 4, 5);
294 check (one[4] == '\0' && one[5] == 'x', 6);
295 check (stpncpy (one, "abcd", 6) == one + 4, 7);
296 check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8);
299 static void
300 test_strcat (void)
302 it = "strcat";
303 (void) strcpy (one, "ijk");
304 check (strcat (one, "lmn") == one, 1); /* Returned value. */
305 equal (one, "ijklmn", 2); /* Basic test. */
307 (void) strcpy (one, "x");
308 (void) strcat (one, "yz");
309 equal (one, "xyz", 3); /* Writeover. */
310 equal (one+4, "mn", 4); /* Wrote too much? */
312 (void) strcpy (one, "gh");
313 (void) strcpy (two, "ef");
314 (void) strcat (one, two);
315 equal (one, "ghef", 5); /* Basic test encore. */
316 equal (two, "ef", 6); /* Stomped on source? */
318 (void) strcpy (one, "");
319 (void) strcat (one, "");
320 equal (one, "", 7); /* Boundary conditions. */
321 (void) strcpy (one, "ab");
322 (void) strcat (one, "");
323 equal (one, "ab", 8);
324 (void) strcpy (one, "");
325 (void) strcat (one, "cd");
326 equal (one, "cd", 9);
328 int ntest = 10;
329 char buf1[80] __attribute__ ((aligned (16)));
330 char buf2[32] __attribute__ ((aligned (16)));
331 for (size_t n1 = 0; n1 < 16; ++n1)
332 for (size_t n2 = 0; n2 < 16; ++n2)
333 for (size_t n3 = 0; n3 < 32; ++n3)
335 size_t olderrors = errors;
337 memset (buf1, 'b', sizeof (buf1));
339 memset (buf1 + n2, 'a', n3);
340 buf1[n2 + n3] = '\0';
341 strcpy (buf2 + n1, "123");
343 check (strcat (buf1 + n2, buf2 + n1) == buf1 + n2, ntest);
344 if (errors == olderrors)
345 for (size_t i = 0; i < sizeof (buf1); ++i)
347 if (i < n2)
348 check (buf1[i] == 'b', ntest);
349 else if (i < n2 + n3)
350 check (buf1[i] == 'a', ntest);
351 else if (i < n2 + n3 + 3)
352 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
353 else if (i == n2 + n3 + 3)
354 check (buf1[i] == '\0', ntest);
355 else
356 check (buf1[i] == 'b', ntest);
358 if (errors != olderrors)
360 printf ("n1=%zu, n2=%zu, n3=%zu, buf1=%02hhx",
361 n1, n2, n3, buf1[0]);
362 for (size_t j = 1; j < sizeof (buf1); ++j)
363 printf (",%02hhx", buf1[j]);
364 putchar_unlocked ('\n');
365 break;
371 static void
372 test_strncat (void)
374 /* First test it as strcat, with big counts, then test the count
375 mechanism. */
376 it = "strncat";
377 (void) strcpy (one, "ijk");
378 check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */
379 equal (one, "ijklmn", 2); /* Basic test. */
381 (void) strcpy (one, "x");
382 (void) strncat (one, "yz", 99);
383 equal (one, "xyz", 3); /* Writeover. */
384 equal (one+4, "mn", 4); /* Wrote too much? */
386 (void) strcpy (one, "gh");
387 (void) strcpy (two, "ef");
388 (void) strncat (one, two, 99);
389 equal (one, "ghef", 5); /* Basic test encore. */
390 equal (two, "ef", 6); /* Stomped on source? */
392 (void) strcpy (one, "");
393 (void) strncat (one, "", 99);
394 equal (one, "", 7); /* Boundary conditions. */
395 (void) strcpy (one, "ab");
396 (void) strncat (one, "", 99);
397 equal (one, "ab", 8);
398 (void) strcpy (one, "");
399 (void) strncat (one, "cd", 99);
400 equal (one, "cd", 9);
402 (void) strcpy (one, "ab");
403 (void) strncat (one, "cdef", 2);
404 equal (one, "abcd", 10); /* Count-limited. */
406 (void) strncat (one, "gh", 0);
407 equal (one, "abcd", 11); /* Zero count. */
409 (void) strncat (one, "gh", 2);
410 equal (one, "abcdgh", 12); /* Count and length equal. */
412 (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */
413 equal (one, "abcdghij", 13);
415 int ntest = 14;
416 char buf1[80] __attribute__ ((aligned (16)));
417 char buf2[32] __attribute__ ((aligned (16)));
418 for (size_t n1 = 0; n1 < 16; ++n1)
419 for (size_t n2 = 0; n2 < 16; ++n2)
420 for (size_t n3 = 0; n3 < 32; ++n3)
421 for (size_t n4 = 0; n4 < 16; ++n4)
423 size_t olderrors = errors;
425 memset (buf1, 'b', sizeof (buf1));
427 memset (buf1 + n2, 'a', n3);
428 buf1[n2 + n3] = '\0';
429 strcpy (buf2 + n1, "123");
431 check (strncat (buf1 + n2, buf2 + n1, ~((size_t) 0) - n4)
432 == buf1 + n2, ntest);
433 if (errors == olderrors)
434 for (size_t i = 0; i < sizeof (buf1); ++i)
436 if (i < n2)
437 check (buf1[i] == 'b', ntest);
438 else if (i < n2 + n3)
439 check (buf1[i] == 'a', ntest);
440 else if (i < n2 + n3 + 3)
441 check (buf1[i] == "123"[i - (n2 + n3)], ntest);
442 else if (i == n2 + n3 + 3)
443 check (buf1[i] == '\0', ntest);
444 else
445 check (buf1[i] == 'b', ntest);
447 if (errors != olderrors)
449 printf ("n1=%zu, n2=%zu, n3=%zu, n4=%zu, buf1=%02hhx",
450 n1, n2, n3, n4, buf1[0]);
451 for (size_t j = 1; j < sizeof (buf1); ++j)
452 printf (",%02hhx", buf1[j]);
453 putchar_unlocked ('\n');
454 break;
460 static void
461 test_strncmp (void)
463 /* First test as strcmp with big counts, then test count code. */
464 it = "strncmp";
465 check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */
466 check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */
467 check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */
468 check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */
469 check (strncmp ("abcd", "abc", 99) > 0, 5);
470 check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */
471 check (strncmp ("abce", "abcd", 99) > 0, 7);
472 check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */
473 check (strncmp ("a\203", "a\003", 2) > 0, 9);
474 check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */
475 check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */
476 check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */
477 check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */
478 check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */
479 check (strncmp ("abc", "abc", (size_t)-2) == 0, 15);
482 static void
483 test_strncpy (void)
485 /* Testing is a bit different because of odd semantics. */
486 it = "strncpy";
487 check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */
488 equal (one, "abc", 2); /* Did the copy go right? */
490 (void) strcpy (one, "abcdefgh");
491 (void) strncpy (one, "xyz", 2);
492 equal (one, "xycdefgh", 3); /* Copy cut by count. */
494 (void) strcpy (one, "abcdefgh");
495 (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */
496 equal (one, "xyzdefgh", 4);
498 (void) strcpy (one, "abcdefgh");
499 (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */
500 equal (one, "xyz", 5);
501 equal (one+4, "efgh", 6); /* Wrote too much? */
503 (void) strcpy (one, "abcdefgh");
504 (void) strncpy (one, "xyz", 5); /* Copy includes padding. */
505 equal (one, "xyz", 7);
506 equal (one+4, "", 8);
507 equal (one+5, "fgh", 9);
509 (void) strcpy (one, "abc");
510 (void) strncpy (one, "xyz", 0); /* Zero-length copy. */
511 equal (one, "abc", 10);
513 (void) strncpy (one, "", 2); /* Zero-length source. */
514 equal (one, "", 11);
515 equal (one+1, "", 12);
516 equal (one+2, "c", 13);
518 (void) strcpy (one, "hi there");
519 (void) strncpy (two, one, 9);
520 equal (two, "hi there", 14); /* Just paranoia. */
521 equal (one, "hi there", 15); /* Stomped on source? */
524 static void
525 test_strlen (void)
527 it = "strlen";
528 check (strlen ("") == 0, 1); /* Empty. */
529 check (strlen ("a") == 1, 2); /* Single char. */
530 check (strlen ("abcd") == 4, 3); /* Multiple chars. */
532 char buf[4096];
533 int i;
534 char *p;
535 for (i=0; i < 0x100; i++)
537 p = (char *) ((uintptr_t)(buf + 0xff) & ~0xff) + i;
538 strcpy (p, "OK");
539 strcpy (p+3, "BAD/WRONG");
540 check (strlen (p) == 2, 4+i);
545 static void
546 test_strnlen (void)
548 it = "strnlen";
549 check (strnlen ("", 10) == 0, 1); /* Empty. */
550 check (strnlen ("a", 10) == 1, 2); /* Single char. */
551 check (strnlen ("abcd", 10) == 4, 3); /* Multiple chars. */
552 check (strnlen ("foo", (size_t) -1) == 3, 4); /* limits of n. */
553 check (strnlen ("abcd", 0) == 0, 5); /* Restricted. */
554 check (strnlen ("abcd", 1) == 1, 6); /* Restricted. */
555 check (strnlen ("abcd", 2) == 2, 7); /* Restricted. */
556 check (strnlen ("abcd", 3) == 3, 8); /* Restricted. */
557 check (strnlen ("abcd", 4) == 4, 9); /* Restricted. */
559 char buf[4096];
560 for (int i = 0; i < 0x100; ++i)
562 char *p = (char *) ((uintptr_t)(buf + 0xff) & ~0xff) + i;
563 strcpy (p, "OK");
564 strcpy (p + 3, "BAD/WRONG");
565 check (strnlen (p, 100) == 2, 10 + i);
569 static void
570 test_strchr (void)
572 it = "strchr";
573 check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */
574 (void) strcpy (one, "abcd");
575 check (strchr (one, 'c') == one+2, 2); /* Basic test. */
576 check (strchr (one, 'd') == one+3, 3); /* End of string. */
577 check (strchr (one, 'a') == one, 4); /* Beginning. */
578 check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */
579 (void) strcpy (one, "ababa");
580 check (strchr (one, 'b') == one+1, 6); /* Finding first. */
581 (void) strcpy (one, "");
582 check (strchr (one, 'b') == NULL, 7); /* Empty string. */
583 check (strchr (one, '\0') == one, 8); /* NUL in empty string. */
585 char buf[4096];
586 int i;
587 char *p;
588 for (i=0; i < 0x100; i++)
590 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
591 strcpy (p, "OK");
592 strcpy (p+3, "BAD/WRONG");
593 check (strchr (p, '/') == NULL, 9+i);
598 static void
599 test_strchrnul (void)
601 const char *os;
602 it = "strchrnul";
603 cp = strchrnul ((os = "abcd"), 'z');
604 check (*cp == '\0', 1); /* Not found. */
605 check (cp == os + 4, 2);
606 (void) strcpy (one, "abcd");
607 check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */
608 check (strchrnul (one, 'd') == one+3, 4); /* End of string. */
609 check (strchrnul (one, 'a') == one, 5); /* Beginning. */
610 check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */
611 (void) strcpy (one, "ababa");
612 check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */
613 (void) strcpy (one, "");
614 check (strchrnul (one, 'b') == one, 8); /* Empty string. */
615 check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */
617 char buf[4096];
618 int i;
619 char *p;
620 for (i=0; i < 0x100; i++)
622 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
623 strcpy (p, "OK");
624 strcpy (p+3, "BAD/WRONG");
625 cp = strchrnul (p, '/');
626 check (*cp == '\0', 9+2*i);
627 check (cp == p+2, 10+2*i);
632 static void
633 test_rawmemchr (void)
635 it = "rawmemchr";
636 (void) strcpy (one, "abcd");
637 check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */
638 check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */
639 check (rawmemchr (one, 'a') == one, 3); /* Beginning. */
640 check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */
641 (void) strcpy (one, "ababa");
642 check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */
643 (void) strcpy (one, "");
644 check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */
646 char buf[4096];
647 int i;
648 char *p;
649 for (i=0; i < 0x100; i++)
651 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
652 strcpy (p, "OK");
653 strcpy (p+3, "BAD/WRONG");
654 check (rawmemchr (p, 'R') == p+8, 6+i);
659 static void
660 test_index (void)
662 it = "index";
663 check (index ("abcd", 'z') == NULL, 1); /* Not found. */
664 (void) strcpy (one, "abcd");
665 check (index (one, 'c') == one+2, 2); /* Basic test. */
666 check (index (one, 'd') == one+3, 3); /* End of string. */
667 check (index (one, 'a') == one, 4); /* Beginning. */
668 check (index (one, '\0') == one+4, 5); /* Finding NUL. */
669 (void) strcpy (one, "ababa");
670 check (index (one, 'b') == one+1, 6); /* Finding first. */
671 (void) strcpy (one, "");
672 check (index (one, 'b') == NULL, 7); /* Empty string. */
673 check (index (one, '\0') == one, 8); /* NUL in empty string. */
676 static void
677 test_strrchr (void)
679 it = "strrchr";
680 check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */
681 (void) strcpy (one, "abcd");
682 check (strrchr (one, 'c') == one+2, 2); /* Basic test. */
683 check (strrchr (one, 'd') == one+3, 3); /* End of string. */
684 check (strrchr (one, 'a') == one, 4); /* Beginning. */
685 check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */
686 (void) strcpy (one, "ababa");
687 check (strrchr (one, 'b') == one+3, 6); /* Finding last. */
688 (void) strcpy (one, "");
689 check (strrchr (one, 'b') == NULL, 7); /* Empty string. */
690 check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */
692 char buf[4096];
693 int i;
694 char *p;
695 for (i=0; i < 0x100; i++)
697 p = (char *) ((uintptr_t) (buf + 0xff) & ~0xff) + i;
698 strcpy (p, "OK");
699 strcpy (p+3, "BAD/WRONG");
700 check (strrchr (p, '/') == NULL, 9+i);
705 static void
706 test_memrchr (void)
708 size_t l;
709 it = "memrchr";
710 check (memrchr ("abcd", 'z', 5) == NULL, 1); /* Not found. */
711 (void) strcpy (one, "abcd");
712 l = strlen (one) + 1;
713 check (memrchr (one, 'c', l) == one+2, 2); /* Basic test. */
714 check (memrchr (one, 'd', l) == one+3, 3); /* End of string. */
715 check (memrchr (one, 'a', l) == one, 4); /* Beginning. */
716 check (memrchr (one, '\0', l) == one+4, 5); /* Finding NUL. */
717 (void) strcpy (one, "ababa");
718 l = strlen (one) + 1;
719 check (memrchr (one, 'b', l) == one+3, 6); /* Finding last. */
720 (void) strcpy (one, "");
721 l = strlen (one) + 1;
722 check (memrchr (one, 'b', l) == NULL, 7); /* Empty string. */
723 check (memrchr (one, '\0', l) == one, 8); /* NUL in empty string. */
725 /* now test all possible alignment and length combinations to catch
726 bugs due to unrolled loops (assuming unrolling is limited to no
727 more than 128 byte chunks: */
729 char buf[128 + sizeof (long)];
730 long align, len, i, pos, n = 9;
732 for (align = 0; align < (long) sizeof (long); ++align) {
733 for (len = 0; len < (long) (sizeof (buf) - align); ++len) {
734 for (i = 0; i < len; ++i)
735 buf[align + i] = 'x'; /* don't depend on memset... */
737 for (pos = len - 1; pos >= 0; --pos) {
738 #if 0
739 printf("align %d, len %d, pos %d\n", align, len, pos);
740 #endif
741 check(memrchr(buf + align, 'x', len) == buf + align + pos, n++);
742 check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
743 n++);
744 buf[align + pos] = '-';
751 static void
752 test_rindex (void)
754 it = "rindex";
755 check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */
756 (void) strcpy (one, "abcd");
757 check (rindex (one, 'c') == one+2, 2); /* Basic test. */
758 check (rindex (one, 'd') == one+3, 3); /* End of string. */
759 check (rindex (one, 'a') == one, 4); /* Beginning. */
760 check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */
761 (void) strcpy (one, "ababa");
762 check (rindex (one, 'b') == one+3, 6); /* Finding last. */
763 (void) strcpy (one, "");
764 check (rindex (one, 'b') == NULL, 7); /* Empty string. */
765 check (rindex (one, '\0') == one, 8); /* NUL in empty string. */
768 static void
769 test_strpbrk (void)
771 it = "strpbrk";
772 check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */
773 (void) strcpy(one, "abcd");
774 check(strpbrk(one, "c") == one+2, 2); /* Basic test. */
775 check(strpbrk(one, "d") == one+3, 3); /* End of string. */
776 check(strpbrk(one, "a") == one, 4); /* Beginning. */
777 check(strpbrk(one, "") == NULL, 5); /* Empty search list. */
778 check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */
779 (void) strcpy(one, "abcabdea");
780 check(strpbrk(one, "b") == one+1, 7); /* Finding first. */
781 check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */
782 check(strpbrk(one, "db") == one+1, 9); /* Another variant. */
783 (void) strcpy(one, "");
784 check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */
785 (void) strcpy(one, "");
786 check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */
787 (void) strcpy(one, "");
788 check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */
789 check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */
790 (void) strcpy(one, "abcabdea");
791 check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */
792 check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */
793 check(strpbrk(one, "db") == one+1, 16); /* Another variant. */
794 check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */
797 static void
798 test_strstr (void)
800 it = "strstr";
801 check(strstr("abcd", "z") == NULL, 1); /* Not found. */
802 check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */
803 (void) strcpy(one, "abcd");
804 check(strstr(one, "c") == one+2, 3); /* Basic test. */
805 check(strstr(one, "bc") == one+1, 4); /* Multichar. */
806 check(strstr(one, "d") == one+3, 5); /* End of string. */
807 check(strstr(one, "cd") == one+2, 6); /* Tail of string. */
808 check(strstr(one, "abc") == one, 7); /* Beginning. */
809 check(strstr(one, "abcd") == one, 8); /* Exact match. */
810 check(strstr(one, "abcde") == NULL, 9); /* Too long. */
811 check(strstr(one, "de") == NULL, 10); /* Past end. */
812 check(strstr(one, "") == one, 11); /* Finding empty. */
813 (void) strcpy(one, "ababa");
814 check(strstr(one, "ba") == one+1, 12); /* Finding first. */
815 (void) strcpy(one, "");
816 check(strstr(one, "b") == NULL, 13); /* Empty string. */
817 check(strstr(one, "") == one, 14); /* Empty in empty string. */
818 (void) strcpy(one, "bcbca");
819 check(strstr(one, "bca") == one+2, 15); /* False start. */
820 (void) strcpy(one, "bbbcabbca");
821 check(strstr(one, "bbca") == one+1, 16); /* With overlap. */
824 static void
825 test_strspn (void)
827 it = "strspn";
828 check(strspn("abcba", "abc") == 5, 1); /* Whole string. */
829 check(strspn("abcba", "ab") == 2, 2); /* Partial. */
830 check(strspn("abc", "qx") == 0, 3); /* None. */
831 check(strspn("", "ab") == 0, 4); /* Null string. */
832 check(strspn("abc", "") == 0, 5); /* Null search list. */
835 static void
836 test_strcspn (void)
838 it = "strcspn";
839 check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */
840 check(strcspn("abcba", "cx") == 2, 2); /* Partial. */
841 check(strcspn("abc", "abc") == 0, 3); /* None. */
842 check(strcspn("", "ab") == 0, 4); /* Null string. */
843 check(strcspn("abc", "") == 3, 5); /* Null search list. */
846 static void
847 test_strtok (void)
849 it = "strtok";
850 (void) strcpy(one, "first, second, third");
851 equal(strtok(one, ", "), "first", 1); /* Basic test. */
852 equal(one, "first", 2);
853 equal(strtok((char *)NULL, ", "), "second", 3);
854 equal(strtok((char *)NULL, ", "), "third", 4);
855 check(strtok((char *)NULL, ", ") == NULL, 5);
856 (void) strcpy(one, ", first, ");
857 equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */
858 check(strtok((char *)NULL, ", ") == NULL, 7);
859 (void) strcpy(one, "1a, 1b; 2a, 2b");
860 equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */
861 equal(strtok((char *)NULL, "; "), "1b", 9);
862 equal(strtok((char *)NULL, ", "), "2a", 10);
863 (void) strcpy(two, "x-y");
864 equal(strtok(two, "-"), "x", 11); /* New string before done. */
865 equal(strtok((char *)NULL, "-"), "y", 12);
866 check(strtok((char *)NULL, "-") == NULL, 13);
867 (void) strcpy(one, "a,b, c,, ,d");
868 equal(strtok(one, ", "), "a", 14); /* Different separators. */
869 equal(strtok((char *)NULL, ", "), "b", 15);
870 equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */
871 equal(strtok((char *)NULL, " ,"), "d", 17);
872 check(strtok((char *)NULL, ", ") == NULL, 18);
873 check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */
874 (void) strcpy(one, ", ");
875 check(strtok(one, ", ") == NULL, 20); /* No tokens. */
876 (void) strcpy(one, "");
877 check(strtok(one, ", ") == NULL, 21); /* Empty string. */
878 (void) strcpy(one, "abc");
879 equal(strtok(one, ", "), "abc", 22); /* No delimiters. */
880 check(strtok((char *)NULL, ", ") == NULL, 23);
881 (void) strcpy(one, "abc");
882 equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */
883 check(strtok((char *)NULL, "") == NULL, 25);
884 (void) strcpy(one, "abcdefgh");
885 (void) strcpy(one, "a,b,c");
886 equal(strtok(one, ","), "a", 26); /* Basics again... */
887 equal(strtok((char *)NULL, ","), "b", 27);
888 equal(strtok((char *)NULL, ","), "c", 28);
889 check(strtok((char *)NULL, ",") == NULL, 29);
890 equal(one+6, "gh", 30); /* Stomped past end? */
891 equal(one, "a", 31); /* Stomped old tokens? */
892 equal(one+2, "b", 32);
893 equal(one+4, "c", 33);
896 static void
897 test_strtok_r (void)
899 it = "strtok_r";
900 (void) strcpy(one, "first, second, third");
901 cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */
902 equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */
903 equal(one, "first", 2);
904 equal(strtok_r((char *)NULL, ", ", &cp), "second", 3);
905 equal(strtok_r((char *)NULL, ", ", &cp), "third", 4);
906 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5);
907 (void) strcpy(one, ", first, ");
908 cp = NULL;
909 equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */
910 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7);
911 (void) strcpy(one, "1a, 1b; 2a, 2b");
912 cp = NULL;
913 equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */
914 equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9);
915 equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10);
916 (void) strcpy(two, "x-y");
917 cp = NULL;
918 equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */
919 equal(strtok_r((char *)NULL, "-", &cp), "y", 12);
920 check(strtok_r((char *)NULL, "-", &cp) == NULL, 13);
921 (void) strcpy(one, "a,b, c,, ,d");
922 cp = NULL;
923 equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */
924 equal(strtok_r((char *)NULL, ", ", &cp), "b", 15);
925 equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */
926 equal(strtok_r((char *)NULL, " ,", &cp), "d", 17);
927 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18);
928 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */
929 (void) strcpy(one, ", ");
930 cp = NULL;
931 check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */
932 (void) strcpy(one, "");
933 cp = NULL;
934 check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */
935 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */
936 (void) strcpy(one, "abc");
937 cp = NULL;
938 equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */
939 check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24);
940 (void) strcpy(one, "abc");
941 cp = NULL;
942 equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */
943 check(strtok_r((char *)NULL, "", &cp) == NULL, 26);
944 (void) strcpy(one, "abcdefgh");
945 (void) strcpy(one, "a,b,c");
946 cp = NULL;
947 equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */
948 equal(strtok_r((char *)NULL, ",", &cp), "b", 28);
949 equal(strtok_r((char *)NULL, ",", &cp), "c", 29);
950 check(strtok_r((char *)NULL, ",", &cp) == NULL, 30);
951 equal(one+6, "gh", 31); /* Stomped past end? */
952 equal(one, "a", 32); /* Stomped old tokens? */
953 equal(one+2, "b", 33);
954 equal(one+4, "c", 34);
955 strcpy (one, ":::");
956 cp = NULL;
957 check (strtok_r (one, ":", &cp) == NULL, 35); /* Must store pointer in cp. */
958 check (strtok_r (NULL, ":", &cp) == NULL, 36);
961 static void
962 test_strsep (void)
964 char *ptr;
965 it = "strsep";
966 cp = strcpy(one, "first, second, third");
967 equal(strsep(&cp, ", "), "first", 1); /* Basic test. */
968 equal(one, "first", 2);
969 equal(strsep(&cp, ", "), "", 3);
970 equal(strsep(&cp, ", "), "second", 4);
971 equal(strsep(&cp, ", "), "", 5);
972 equal(strsep(&cp, ", "), "third", 6);
973 check(strsep(&cp, ", ") == NULL, 7);
974 cp = strcpy(one, ", first, ");
975 equal(strsep(&cp, ", "), "", 8);
976 equal(strsep(&cp, ", "), "", 9);
977 equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */
978 equal(strsep(&cp, ", "), "", 11);
979 equal(strsep(&cp, ", "), "", 12);
980 check(strsep(&cp, ", ") == NULL, 13);
981 cp = strcpy(one, "1a, 1b; 2a, 2b");
982 equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */
983 equal(strsep(&cp, ", "), "", 15);
984 equal(strsep(&cp, "; "), "1b", 16);
985 equal(strsep(&cp, ", "), "", 17);
986 equal(strsep(&cp, ", "), "2a", 18);
987 cp = strcpy(two, "x-y");
988 equal(strsep(&cp, "-"), "x", 19); /* New string before done. */
989 equal(strsep(&cp, "-"), "y", 20);
990 check(strsep(&cp, "-") == NULL, 21);
991 cp = strcpy(one, "a,b, c,, ,d ");
992 equal(strsep(&cp, ", "), "a", 22); /* Different separators. */
993 equal(strsep(&cp, ", "), "b", 23);
994 equal(strsep(&cp, " ,"), "", 24);
995 equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */
996 equal(strsep(&cp, " ,"), "", 26);
997 equal(strsep(&cp, " ,"), "", 27);
998 equal(strsep(&cp, " ,"), "", 28);
999 equal(strsep(&cp, " ,"), "d", 29);
1000 equal(strsep(&cp, " ,"), "", 30);
1001 check(strsep(&cp, ", ") == NULL, 31);
1002 check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */
1003 cp = strcpy(one, ", ");
1004 equal(strsep(&cp, ", "), "", 33);
1005 equal(strsep(&cp, ", "), "", 34);
1006 equal(strsep(&cp, ", "), "", 35);
1007 check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */
1008 cp = strcpy(one, "");
1009 equal(strsep(&cp, ", "), "", 37);
1010 check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */
1011 cp = strcpy(one, "abc");
1012 equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */
1013 check(strsep(&cp, ", ") == NULL, 40);
1014 cp = strcpy(one, "abc");
1015 equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */
1016 check(strsep(&cp, "") == NULL, 42);
1017 (void) strcpy(one, "abcdefgh");
1018 cp = strcpy(one, "a,b,c");
1019 equal(strsep(&cp, ","), "a", 43); /* Basics again... */
1020 equal(strsep(&cp, ","), "b", 44);
1021 equal(strsep(&cp, ","), "c", 45);
1022 check(strsep(&cp, ",") == NULL, 46);
1023 equal(one+6, "gh", 47); /* Stomped past end? */
1024 equal(one, "a", 48); /* Stomped old tokens? */
1025 equal(one+2, "b", 49);
1026 equal(one+4, "c", 50);
1029 char text[] = "This,is,a,test";
1030 char *list = strdupa (text);
1031 equal (strsep (&list, ","), "This", 51);
1032 equal (strsep (&list, ","), "is", 52);
1033 equal (strsep (&list, ","), "a", 53);
1034 equal (strsep (&list, ","), "test", 54);
1035 check (strsep (&list, ",") == NULL, 55);
1038 cp = strcpy(one, "a,b, c,, ,d,");
1039 equal(strsep(&cp, ","), "a", 56); /* Different separators. */
1040 equal(strsep(&cp, ","), "b", 57);
1041 equal(strsep(&cp, ","), " c", 58); /* Permute list too. */
1042 equal(strsep(&cp, ","), "", 59);
1043 equal(strsep(&cp, ","), " ", 60);
1044 equal(strsep(&cp, ","), "d", 61);
1045 equal(strsep(&cp, ","), "", 62);
1046 check(strsep(&cp, ",") == NULL, 63);
1047 check(strsep(&cp, ",") == NULL, 64); /* Persistence. */
1049 cp = strcpy(one, "a,b, c,, ,d,");
1050 equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */
1051 equal(strsep(&cp, "x,y"), "b", 66);
1052 equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */
1053 equal(strsep(&cp, "xy,"), "", 68);
1054 equal(strsep(&cp, "x,y"), " ", 69);
1055 equal(strsep(&cp, ",xy"), "d", 70);
1056 equal(strsep(&cp, "xy,"), "", 71);
1057 check(strsep(&cp, "x,y") == NULL, 72);
1058 check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */
1060 cp = strcpy(one, "ABC");
1061 one[4] = ':';
1062 equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */
1063 ptr = strsep(&cp, ":");
1064 equal(ptr, "", 75);
1065 check(ptr == one + 3, 76);
1066 check(cp == NULL, 77);
1068 cp = strcpy(one, "ABC");
1069 one[4] = ':';
1070 equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */
1071 ptr = strsep(&cp, ":.");
1072 equal(ptr, "", 79);
1073 check(ptr == one + 3, 80);
1075 cp = strcpy(one, "ABC"); /* No token in string. */
1076 equal(strsep(&cp, ","), "ABC", 81);
1077 check(cp == NULL, 82);
1079 *one = '\0'; /* Empty string. */
1080 cp = one;
1081 ptr = strsep(&cp, ",");
1082 equal(ptr, "", 83);
1083 check(ptr == one, 84);
1084 check(cp == NULL, 85);
1086 *one = '\0'; /* Empty string and no token. */
1087 cp = one;
1088 ptr = strsep(&cp, "");
1089 equal(ptr, "", 86);
1090 check(ptr == one , 87);
1091 check(cp == NULL, 88);
1094 static void
1095 test_memcmp (void)
1097 int cnt = 1;
1098 char one[21];
1099 char two[21];
1101 it = "memcmp";
1102 check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */
1103 check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */
1104 check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */
1105 check(memcmp("abcf", "abcd", 4) > 0, cnt++);
1106 check(memcmp("alph", "cold", 4) < 0, cnt++);
1107 check(memcmp("a\203", "a\003", 2) > 0, cnt++);
1108 check(memcmp("a\003", "a\203", 2) < 0, cnt++);
1109 check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++);
1110 check(memcmp("abc\203", "abc\003", 4) > 0, cnt++);
1111 check(memcmp("abc\003", "abc\203", 4) < 0, cnt++);
1112 check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */
1113 check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */
1114 /* Comparisons with shifting 4-byte boundaries. */
1115 for (int i = 0; i < 4; ++i)
1117 char *a = one + i;
1118 char *b = two + i;
1119 memcpy(a, "--------11112222", 16);
1120 memcpy(b, "--------33334444", 16);
1121 check(memcmp(b, a, 16) > 0, cnt++);
1122 check(memcmp(a, b, 16) < 0, cnt++);
1126 static void
1127 test_memchr (void)
1129 it = "memchr";
1130 check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */
1131 (void) strcpy(one, "abcd");
1132 check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */
1133 check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */
1134 check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */
1135 check(memchr(one, 'a', 4) == one, 4); /* Beginning. */
1136 check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */
1137 (void) strcpy(one, "ababa");
1138 check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */
1139 check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */
1140 check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */
1141 (void) strcpy(one, "a\203b");
1142 check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */
1144 /* now test all possible alignment and length combinations to catch
1145 bugs due to unrolled loops (assuming unrolling is limited to no
1146 more than 128 byte chunks: */
1148 char buf[128 + sizeof (long)];
1149 long align, len, i, pos;
1151 for (align = 0; align < (long) sizeof (long); ++align) {
1152 for (len = 0; len < (long) (sizeof (buf) - align); ++len) {
1153 for (i = 0; i < len; ++i) {
1154 buf[align + i] = 'x'; /* don't depend on memset... */
1156 for (pos = 0; pos < len; ++pos) {
1157 #if 0
1158 printf("align %d, len %d, pos %d\n", align, len, pos);
1159 #endif
1160 check(memchr(buf + align, 'x', len) == buf + align + pos, 10);
1161 check(memchr(buf + align, 'x', pos) == NULL, 11);
1162 buf[align + pos] = '-';
1169 static void
1170 test_memcpy (void)
1172 int i;
1173 it = "memcpy";
1174 check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */
1175 equal(one, "abc", 2); /* Did the copy go right? */
1177 (void) strcpy(one, "abcdefgh");
1178 (void) memcpy(one+1, "xyz", 2);
1179 equal(one, "axydefgh", 3); /* Basic test. */
1181 (void) strcpy(one, "abc");
1182 (void) memcpy(one, "xyz", 0);
1183 equal(one, "abc", 4); /* Zero-length copy. */
1185 (void) strcpy(one, "hi there");
1186 (void) strcpy(two, "foo");
1187 (void) memcpy(two, one, 9);
1188 equal(two, "hi there", 5); /* Just paranoia. */
1189 equal(one, "hi there", 6); /* Stomped on source? */
1191 for (i = 0; i < 16; i++)
1193 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1194 strcpy (one, x);
1195 check (memcpy (one + i, "hi there", 9) == one + i,
1196 7 + (i * 6)); /* Unaligned destination. */
1197 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1198 equal (one + i, "hi there", 9 + (i * 6));
1199 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1200 check (memcpy (two, one + i, 9) == two,
1201 11 + (i * 6)); /* Unaligned source. */
1202 equal (two, "hi there", 12 + (i * 6));
1206 static void
1207 test_mempcpy (void)
1209 int i;
1210 it = "mempcpy";
1211 check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */
1212 equal(one, "abc", 2); /* Did the copy go right? */
1214 (void) strcpy(one, "abcdefgh");
1215 (void) mempcpy(one+1, "xyz", 2);
1216 equal(one, "axydefgh", 3); /* Basic test. */
1218 (void) strcpy(one, "abc");
1219 (void) mempcpy(one, "xyz", 0);
1220 equal(one, "abc", 4); /* Zero-length copy. */
1222 (void) strcpy(one, "hi there");
1223 (void) strcpy(two, "foo");
1224 (void) mempcpy(two, one, 9);
1225 equal(two, "hi there", 5); /* Just paranoia. */
1226 equal(one, "hi there", 6); /* Stomped on source? */
1228 for (i = 0; i < 16; i++)
1230 const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
1231 strcpy (one, x);
1232 check (mempcpy (one + i, "hi there", 9) == one + i + 9,
1233 7 + (i * 6)); /* Unaligned destination. */
1234 check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */
1235 equal (one + i, "hi there", 9 + (i * 6));
1236 check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */
1237 check (mempcpy (two, one + i, 9) == two + 9,
1238 11 + (i * 6)); /* Unaligned source. */
1239 equal (two, "hi there", 12 + (i * 6));
1243 static void
1244 test_memmove (void)
1246 it = "memmove";
1247 check(memmove(one, "abc", 4) == one, 1); /* Returned value. */
1248 equal(one, "abc", 2); /* Did the copy go right? */
1250 (void) strcpy(one, "abcdefgh");
1251 (void) memmove(one+1, "xyz", 2);
1252 equal(one, "axydefgh", 3); /* Basic test. */
1254 (void) strcpy(one, "abc");
1255 (void) memmove(one, "xyz", 0);
1256 equal(one, "abc", 4); /* Zero-length copy. */
1258 (void) strcpy(one, "hi there");
1259 (void) strcpy(two, "foo");
1260 (void) memmove(two, one, 9);
1261 equal(two, "hi there", 5); /* Just paranoia. */
1262 equal(one, "hi there", 6); /* Stomped on source? */
1264 (void) strcpy(one, "abcdefgh");
1265 (void) memmove(one+1, one, 9);
1266 equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */
1268 (void) strcpy(one, "abcdefgh");
1269 (void) memmove(one+1, one+2, 7);
1270 equal(one, "acdefgh", 8); /* Overlap, left-to-right. */
1272 (void) strcpy(one, "abcdefgh");
1273 (void) memmove(one, one, 9);
1274 equal(one, "abcdefgh", 9); /* 100% overlap. */
1277 static void
1278 test_memccpy (void)
1280 /* First test like memcpy, then the search part The SVID, the only
1281 place where memccpy is mentioned, says overlap might fail, so we
1282 don't try it. Besides, it's hard to see the rationale for a
1283 non-left-to-right memccpy. */
1284 it = "memccpy";
1285 check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */
1286 equal(one, "abc", 2); /* Did the copy go right? */
1288 (void) strcpy(one, "abcdefgh");
1289 (void) memccpy(one+1, "xyz", 'q', 2);
1290 equal(one, "axydefgh", 3); /* Basic test. */
1292 (void) strcpy(one, "abc");
1293 (void) memccpy(one, "xyz", 'q', 0);
1294 equal(one, "abc", 4); /* Zero-length copy. */
1296 (void) strcpy(one, "hi there");
1297 (void) strcpy(two, "foo");
1298 (void) memccpy(two, one, 'q', 9);
1299 equal(two, "hi there", 5); /* Just paranoia. */
1300 equal(one, "hi there", 6); /* Stomped on source? */
1302 (void) strcpy(one, "abcdefgh");
1303 (void) strcpy(two, "horsefeathers");
1304 check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */
1305 equal(one, "abcdefgh", 8); /* Source intact? */
1306 equal(two, "abcdefeathers", 9); /* Copy correct? */
1308 (void) strcpy(one, "abcd");
1309 (void) strcpy(two, "bumblebee");
1310 check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */
1311 equal(two, "aumblebee", 11);
1312 check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */
1313 equal(two, "abcdlebee", 13);
1314 (void) strcpy(one, "xyz");
1315 check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */
1316 equal(two, "xbcdlebee", 15);
1319 static void
1320 test_memset (void)
1322 int i;
1324 it = "memset";
1325 (void) strcpy(one, "abcdefgh");
1326 check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */
1327 equal(one, "axxxefgh", 2); /* Basic test. */
1329 (void) memset(one+2, 'y', 0);
1330 equal(one, "axxxefgh", 3); /* Zero-length set. */
1332 (void) memset(one+5, 0, 1);
1333 equal(one, "axxxe", 4); /* Zero fill. */
1334 equal(one+6, "gh", 5); /* And the leftover. */
1336 (void) memset(one+2, 010045, 1);
1337 equal(one, "ax\045xe", 6); /* Unsigned char convert. */
1339 /* Non-8bit fill character. */
1340 memset (one, 0x101, sizeof (one));
1341 for (i = 0; i < (int) sizeof (one); ++i)
1342 check (one[i] == '\01', 7);
1344 /* Test for more complex versions of memset, for all alignments and
1345 lengths up to 256. This test takes a little while, perhaps it should
1346 be made weaker? */
1348 char data[512];
1349 int j;
1350 int k;
1351 int c;
1353 for (i = 0; i < 512; i++)
1354 data[i] = 'x';
1355 for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and
1356 memset(,'y',) */
1357 for (j = 0; j < 256; j++)
1358 for (i = 0; i < 256; i++)
1360 memset (data + i, c, j);
1361 for (k = 0; k < i; k++)
1362 if (data[k] != 'x')
1363 goto fail;
1364 for (k = i; k < i+j; k++)
1366 if (data[k] != c)
1367 goto fail;
1368 data[k] = 'x';
1370 for (k = i+j; k < 512; k++)
1371 if (data[k] != 'x')
1372 goto fail;
1373 continue;
1375 fail:
1376 check (0, 8 + i + j * 256 + (c != 0) * 256 * 256);
1381 static void
1382 test_bcopy (void)
1384 /* Much like memcpy. Berklix manual is silent about overlap, so
1385 don't test it. */
1386 it = "bcopy";
1387 (void) bcopy("abc", one, 4);
1388 equal(one, "abc", 1); /* Simple copy. */
1390 (void) strcpy(one, "abcdefgh");
1391 (void) bcopy("xyz", one+1, 2);
1392 equal(one, "axydefgh", 2); /* Basic test. */
1394 (void) strcpy(one, "abc");
1395 (void) bcopy("xyz", one, 0);
1396 equal(one, "abc", 3); /* Zero-length copy. */
1398 (void) strcpy(one, "hi there");
1399 (void) strcpy(two, "foo");
1400 (void) bcopy(one, two, 9);
1401 equal(two, "hi there", 4); /* Just paranoia. */
1402 equal(one, "hi there", 5); /* Stomped on source? */
1405 static void
1406 test_bzero (void)
1408 it = "bzero";
1409 (void) strcpy(one, "abcdef");
1410 bzero(one+2, 2);
1411 equal(one, "ab", 1); /* Basic test. */
1412 equal(one+3, "", 2);
1413 equal(one+4, "ef", 3);
1415 (void) strcpy(one, "abcdef");
1416 bzero(one+2, 0);
1417 equal(one, "abcdef", 4); /* Zero-length copy. */
1420 static void
1421 test_strndup (void)
1423 char *p, *q;
1424 it = "strndup";
1425 p = strndup("abcdef", 12);
1426 check(p != NULL, 1);
1427 if (p != NULL)
1429 equal(p, "abcdef", 2);
1430 q = strndup(p + 1, 2);
1431 check(q != NULL, 3);
1432 if (q != NULL)
1433 equal(q, "bc", 4);
1434 free (q);
1436 free (p);
1437 p = strndup("abc def", 3);
1438 check(p != NULL, 5);
1439 if (p != NULL)
1440 equal(p, "abc", 6);
1441 free (p);
1444 static void
1445 test_bcmp (void)
1447 it = "bcmp";
1448 check(bcmp("a", "a", 1) == 0, 1); /* Identity. */
1449 check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1450 check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1451 check(bcmp("abce", "abcd", 4) != 0, 4);
1452 check(bcmp("alph", "beta", 4) != 0, 5);
1453 check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */
1454 check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */
1457 static void
1458 test_memcmpeq (void)
1460 it = "__memcmpeq";
1461 check (__memcmpeq ("a", "a", 1) == 0, 1); /* Identity. */
1462 check (__memcmpeq ("abc", "abc", 3) == 0, 2); /* Multicharacter. */
1463 check (__memcmpeq ("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */
1464 check (__memcmpeq ("abce", "abcd", 4) != 0, 4);
1465 check (__memcmpeq ("alph", "beta", 4) != 0, 5);
1466 check (__memcmpeq ("abce", "abcd", 3) == 0, 6); /* Count limited. */
1467 check (__memcmpeq ("abc", "def", 0) == 0, 8); /* Zero count. */
1470 static void
1471 test_strerror (void)
1473 it = "strerror";
1474 check(strerror(EDOM) != 0, 1);
1475 check(strerror(ERANGE) != 0, 2);
1476 check(strerror(ENOENT) != 0, 3);
1479 static void
1480 test_strcasecmp (void)
1482 it = "strcasecmp";
1483 /* Note that the locale is "C". */
1484 check(strcasecmp("a", "a") == 0, 1);
1485 check(strcasecmp("a", "A") == 0, 2);
1486 check(strcasecmp("A", "a") == 0, 3);
1487 check(strcasecmp("a", "b") < 0, 4);
1488 check(strcasecmp("c", "b") > 0, 5);
1489 check(strcasecmp("abc", "AbC") == 0, 6);
1490 check(strcasecmp("0123456789", "0123456789") == 0, 7);
1491 check(strcasecmp("", "0123456789") < 0, 8);
1492 check(strcasecmp("AbC", "") > 0, 9);
1493 check(strcasecmp("AbC", "A") > 0, 10);
1494 check(strcasecmp("AbC", "Ab") > 0, 11);
1495 check(strcasecmp("AbC", "ab") > 0, 12);
1498 static void
1499 test_strncasecmp (void)
1501 it = "strncasecmp";
1502 /* Note that the locale is "C". */
1503 check(strncasecmp("a", "a", 5) == 0, 1);
1504 check(strncasecmp("a", "A", 5) == 0, 2);
1505 check(strncasecmp("A", "a", 5) == 0, 3);
1506 check(strncasecmp("a", "b", 5) < 0, 4);
1507 check(strncasecmp("c", "b", 5) > 0, 5);
1508 check(strncasecmp("abc", "AbC", 5) == 0, 6);
1509 check(strncasecmp("0123456789", "0123456789", 10) == 0, 7);
1510 check(strncasecmp("", "0123456789", 10) < 0, 8);
1511 check(strncasecmp("AbC", "", 5) > 0, 9);
1512 check(strncasecmp("AbC", "A", 5) > 0, 10);
1513 check(strncasecmp("AbC", "Ab", 5) > 0, 11);
1514 check(strncasecmp("AbC", "ab", 5) > 0, 12);
1515 check(strncasecmp("0123456789", "AbC", 0) == 0, 13);
1516 check(strncasecmp("AbC", "abc", 1) == 0, 14);
1517 check(strncasecmp("AbC", "abc", 2) == 0, 15);
1518 check(strncasecmp("AbC", "abc", 3) == 0, 16);
1519 check(strncasecmp("AbC", "abcd", 3) == 0, 17);
1520 check(strncasecmp("AbC", "abcd", 4) < 0, 18);
1521 check(strncasecmp("ADC", "abcd", 1) == 0, 19);
1522 check(strncasecmp("ADC", "abcd", 2) > 0, 20);
1526 main (void)
1528 int status;
1530 /* Test strcmp first because we use it to test other things. */
1531 test_strcmp ();
1533 /* Test strcpy next because we need it to set up other tests. */
1534 test_strcpy ();
1536 /* A closely related function is stpcpy. */
1537 test_stpcpy ();
1539 /* stpncpy. */
1540 test_stpncpy ();
1542 /* strcat. */
1543 test_strcat ();
1545 /* strncat. */
1546 test_strncat ();
1548 /* strncmp. */
1549 test_strncmp ();
1551 /* strncpy. */
1552 test_strncpy ();
1554 /* strlen. */
1555 test_strlen ();
1557 /* strnlen. */
1558 test_strnlen ();
1560 /* strchr. */
1561 test_strchr ();
1563 /* strchrnul. */
1564 test_strchrnul ();
1566 /* rawmemchr. */
1567 test_rawmemchr ();
1569 /* index - just like strchr. */
1570 test_index ();
1572 /* strrchr. */
1573 test_strrchr ();
1575 /* memrchr. */
1576 test_memrchr ();
1578 /* rindex - just like strrchr. */
1579 test_rindex ();
1581 /* strpbrk - somewhat like strchr. */
1582 test_strpbrk ();
1584 /* strstr - somewhat like strchr. */
1585 test_strstr ();
1587 /* strspn. */
1588 test_strspn ();
1590 /* strcspn. */
1591 test_strcspn ();
1593 /* strtok - the hard one. */
1594 test_strtok ();
1596 /* strtok_r. */
1597 test_strtok_r ();
1599 /* strsep. */
1600 test_strsep ();
1602 /* memcmp. */
1603 test_memcmp ();
1605 /* memchr. */
1606 test_memchr ();
1608 /* memcpy - need not work for overlap. */
1609 test_memcpy ();
1611 /* memmove - must work on overlap. */
1612 test_memmove ();
1614 /* mempcpy */
1615 test_mempcpy ();
1617 /* memccpy. */
1618 test_memccpy ();
1620 /* memset. */
1621 test_memset ();
1623 /* bcopy. */
1624 test_bcopy ();
1626 /* bzero. */
1627 test_bzero ();
1629 /* bcmp - somewhat like memcmp. */
1630 test_bcmp ();
1632 /* __memcmpeq - somewhat like memcmp. */
1633 test_memcmpeq ();
1635 /* strndup. */
1636 test_strndup ();
1638 /* strerror - VERY system-dependent. */
1639 test_strerror ();
1641 /* strcasecmp. Without locale dependencies. */
1642 test_strcasecmp ();
1644 /* strncasecmp. Without locale dependencies. */
1645 test_strncasecmp ();
1647 if (errors == 0)
1649 status = EXIT_SUCCESS;
1650 puts("No errors.");
1652 else
1654 status = EXIT_FAILURE;
1655 printf("%zd errors.\n", errors);
1658 return status;