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