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