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