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