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

source code of glibc/string/tester.c