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