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