]> git.proxmox.com Git - efi-boot-shim.git/blob - test-str.c
9cb831deef9f0a1bc9e4af30dd64ff8c05c6ab3a
[efi-boot-shim.git] / test-str.c
1 // SPDX-License-Identifier: BSD-2-Clause-Patent
2 /*
3 * test-str.c - test our string functions.
4 */
5 #pragma GCC diagnostic ignored "-Wunused-variable"
6 #pragma GCC diagnostic error "-Wnonnull"
7 #pragma GCC diagnostic error "-Wunused-function"
8
9 #pragma GCC diagnostic warning "-Wcpp"
10
11 #ifndef SHIM_UNIT_TEST
12 #define SHIM_UNIT_TEST
13 #endif
14 #include "shim.h"
15
16 #include <stdio.h>
17
18 static int
19 test_strlen(void)
20 {
21 const char s1[] = "abcd";
22 const char s2[] = "";
23
24 assert_equal_return(shim_strlen(s1), 4, -1, "got %d expected %d\n");
25 assert_equal_return(strlen(s1), 4, -1, "got %d expected %d\n");
26 assert_equal_return(shim_strlen(s2), 0, -1, "got %d expected %d\n");
27 assert_equal_return(strlen(s2), 0, -1, "got %d expected %d\n");
28
29 return 0;
30 }
31
32 static int
33 test_strnlen(void)
34 {
35 const char s1[] = "abcd";
36 const char s2[] = "";
37
38 assert_equal_return(shim_strnlen(s1, 0), 0, -1, "got %d expected %d\n");
39 assert_equal_return(strnlen(s1, 0), 0, -1, "got %d expected %d\n");
40 assert_equal_return(shim_strnlen(s1, 1), 1, -1, "got %d expected %d\n");
41 assert_equal_return(strnlen(s1, 1), 1, -1, "got %d expected %d\n");
42 assert_equal_return(shim_strnlen(s1, 3), 3, -1, "got %d expected %d\n");
43 assert_equal_return(strnlen(s1, 3), 3, -1, "got %d expected %d\n");
44 assert_equal_return(shim_strnlen(s1, 4), 4, -1, "got %d expected %d\n");
45 assert_equal_return(strnlen(s1, 4), 4, -1, "got %d expected %d\n");
46 assert_equal_return(shim_strnlen(s1, 5), 4, -1, "got %d expected %d\n");
47 assert_equal_return(strnlen(s1, 5), 4, -1, "got %d expected %d\n");
48 assert_equal_return(shim_strnlen(s2, 0), 0, -1, "got %d expected %d\n");
49 assert_equal_return(strnlen(s2, 0), 0, -1, "got %d expected %d\n");
50 assert_equal_return(shim_strnlen(s2, 1), 0, -1, "got %d expected %d\n");
51 assert_equal_return(strnlen(s2, 1), 0, -1, "got %d expected %d\n");
52
53 return 0;
54 }
55
56 #pragma GCC diagnostic push
57 #pragma GCC diagnostic ignored "-Wshadow"
58
59 /*
60 * these are constants so that the failures are readable if you get
61 * it wrong.
62 */
63 #define s0 "sbat,"
64 #define s0sz 6
65 #define s0len 5
66 #define s1 "sbat,1,2021030218"
67 #define s1sz 18
68 #define s1len 17
69 #define s2 "sbat,1,20210302"
70 #define s2sz 16
71 #define s2len 15
72 #define s3 "sbat,1,20210303"
73 #define s3sz 16
74 #define s3len 15
75 #define s4 "sbat\314\234\014,"
76 #define s4sz 9
77 #define s4len 8
78 /*
79 * same as s4 but with a UTF8 encoding error; one bit is cleared.
80 */
81 #define s5 "sbat\314\034\014,"
82 #define s5sz 9
83 #define s5len 8
84
85 #define test_strcmp_helper(fn, invert_sign_errors, invert_encoding_errors) \
86 ({ \
87 printf("testing %s\n", #fn); \
88 int status_ = 0, rc_; \
89 \
90 rc_ = assert_zero_as_expr(fn(s0, s0), -1, "\n"); \
91 status_ = MIN(status_, rc_); \
92 \
93 if (invert_sign_errors) \
94 rc_ = assert_positive_as_expr(fn(s0, s1), -1, "\n"); \
95 else \
96 rc_ = assert_negative_as_expr(fn(s0, s1), -1, "\n"); \
97 status_ = MIN(status_, rc_); \
98 rc_ = assert_positive_as_expr(fn(s1, s0), -1, "\n"); \
99 status_ = MIN(status_, rc_); \
100 \
101 rc_ = assert_positive_as_expr(fn(s1, s2), -1, "\n"); \
102 status_ = MIN(status_, rc_); \
103 if (invert_sign_errors) \
104 rc_ = assert_positive_as_expr(fn(s2, s1), -1, "\n"); \
105 else \
106 rc_ = assert_negative_as_expr(fn(s2, s1), -1, "\n"); \
107 status_ = MIN(status_, rc_); \
108 \
109 if (invert_sign_errors) \
110 rc_ = assert_positive_as_expr(fn(s2, s3), -1, "\n"); \
111 else \
112 rc_ = assert_negative_as_expr(fn(s2, s3), -1, "\n"); \
113 status_ = MIN(status_, rc_); \
114 rc_ = assert_positive_as_expr(fn(s3, s2), -1, "\n"); \
115 status_ = MIN(status_, rc_); \
116 \
117 if (invert_encoding_errors) \
118 rc_ = assert_negative_as_expr(fn(s4, s5), -1, "\n"); \
119 else \
120 rc_ = assert_positive_as_expr(fn(s4, s5), -1, "\n"); \
121 status_ = MIN(status_, rc_); \
122 \
123 if (status_ < 0) \
124 printf("%s failed\n", #fn); \
125 status_; \
126 })
127
128 static int
129 test_strcmp(void)
130 {
131 int status = 0;
132 int rc;
133
134 /*
135 * shim's strcmp
136 */
137 rc = test_strcmp_helper(shim_strcmp, false, false);
138 status = MIN(rc, status);
139
140 /*
141 * libc's strcmp
142 */
143 rc = test_strcmp_helper(strcmp, false, false);
144 status = MIN(rc, status);
145
146 return status;
147 }
148
149 #undef s0
150 #undef s0sz
151 #undef s0len
152 #undef s1
153 #undef s1sz
154 #undef s1len
155 #undef s2
156 #undef s2sz
157 #undef s2len
158 #undef s3
159 #undef s3sz
160 #undef s3len
161 #undef s4
162 #undef s4sz
163 #undef s4len
164 #undef s5
165 #undef s5sz
166 #undef s5len
167
168 /*
169 * these are constants so that the failures are readable if you get
170 * it wrong.
171 */
172 #define s0 "sbAt,"
173 #define s0sz 6
174 #define s0len 5
175 #define s1 "sbaT,1,2021030218"
176 #define s1sz 18
177 #define s1len 17
178 #define s2 "sbAt,1,20210302"
179 #define s2sz 16
180 #define s2len 15
181 #define s3 "sbaT,1,20210303"
182 #define s3sz 16
183 #define s3len 15
184 #define s4 "sbat\314\234\014,"
185 #define s4sz 9
186 #define s4len 8
187 /*
188 * same as s4 but with a UTF8 encoding error; one bit is cleared.
189 */
190 #define s5 "sbat\314\034\014,"
191 #define s5sz 9
192 #define s5len 8
193
194 #define test_strcasecmp_helper(fn, invert_sign_errors, invert_encoding_errors) \
195 ({ \
196 printf("testing %s\n", #fn); \
197 int status_ = 0, rc_; \
198 \
199 rc_ = assert_zero_as_expr(fn(s0, s0), -1, "\n"); \
200 status_ = MIN(status_, rc_); \
201 \
202 if (invert_sign_errors) \
203 rc_ = assert_positive_as_expr(fn(s0, s1), -1, "\n"); \
204 else \
205 rc_ = assert_negative_as_expr(fn(s0, s1), -1, "\n"); \
206 status_ = MIN(status_, rc_); \
207 rc_ = assert_positive_as_expr(fn(s1, s0), -1, "\n"); \
208 status_ = MIN(status_, rc_); \
209 \
210 rc_ = assert_positive_as_expr(fn(s1, s2), -1, "\n"); \
211 status_ = MIN(status_, rc_); \
212 if (invert_sign_errors) \
213 rc_ = assert_positive_as_expr(fn(s2, s1), -1, "\n"); \
214 else \
215 rc_ = assert_negative_as_expr(fn(s2, s1), -1, "\n"); \
216 status_ = MIN(status_, rc_); \
217 \
218 if (invert_sign_errors) \
219 rc_ = assert_positive_as_expr(fn(s2, s3), -1, "\n"); \
220 else \
221 rc_ = assert_negative_as_expr(fn(s2, s3), -1, "\n"); \
222 status_ = MIN(status_, rc_); \
223 rc_ = assert_positive_as_expr(fn(s3, s2), -1, "\n"); \
224 status_ = MIN(status_, rc_); \
225 \
226 if (invert_encoding_errors) \
227 rc_ = assert_negative_as_expr(fn(s4, s5), -1, "\n"); \
228 else \
229 rc_ = assert_positive_as_expr(fn(s4, s5), -1, "\n"); \
230 status_ = MIN(status_, rc_); \
231 \
232 if (status_ < 0) \
233 printf("%s failed\n", #fn); \
234 status_; \
235 })
236
237 static int
238 test_strcasecmp(void)
239 {
240 int status = 0;
241 int rc;
242
243 /*
244 * shim's strcasecmp
245 */
246 rc = test_strcasecmp_helper(shim_strcasecmp, false, false);
247 status = MIN(rc, status);
248
249 /*
250 * libc's strcasecmp
251 */
252 rc = test_strcasecmp_helper(strcasecmp, false, false);
253 status = MIN(rc, status);
254
255 return status;
256 }
257
258 #undef s0
259 #undef s0sz
260 #undef s0len
261 #undef s1
262 #undef s1sz
263 #undef s1len
264 #undef s2
265 #undef s2sz
266 #undef s2len
267 #undef s3
268 #undef s3sz
269 #undef s3len
270 #undef s4
271 #undef s4sz
272 #undef s4len
273 #undef s5
274 #undef s5sz
275 #undef s5len
276
277 /*
278 * these are constants so that the failures are readable if you get
279 * it wrong.
280 */
281 #define s0 "sbAt,"
282 #define s0sz 6
283 #define s0len 5
284 #define s1 "sbaT,1,2021030218"
285 #define s1sz 18
286 #define s1len 17
287 #define s2 "sbAt,1,20210302"
288 #define s2sz 16
289 #define s2len 15
290 #define s3 "sbaT,1,20210303"
291 #define s3sz 16
292 #define s3len 15
293 #define s4 "sbat\314\234\014,"
294 #define s4sz 9
295 #define s4len 8
296 /*
297 * same as s4 but with a UTF8 encoding error; one bit is cleared.
298 */
299 #define s5 "sbat\314\034\014,"
300 #define s5sz 9
301 #define s5len 8
302
303 #define test_strncasecmp_helper(fn, test_cmp_magnitude, invert_sign_errors, \
304 invert_encoding_errors) \
305 ({ \
306 printf("testing %s\n", #fn); \
307 int status_ = 0, rc_; \
308 \
309 rc_ = assert_zero_as_expr(fn(s0, s0, s0len), -1, "\n"); \
310 status_ = MIN(status_, rc_); \
311 rc_ = assert_zero_as_expr(fn(s0, s0, s0sz), -1, "\n"); \
312 status_ = MIN(status_, rc_); \
313 \
314 rc_ = assert_zero_as_expr(fn(s0, s1, s0len), -1, "\n"); \
315 status_ = MIN(status_, rc_); \
316 if (invert_sign_errors) \
317 rc_ = assert_positive_as_expr(fn(s0, s1, s0sz), -1, \
318 "\n"); \
319 else \
320 rc_ = assert_negative_as_expr(fn(s0, s1, s0sz), -1, \
321 "\n"); \
322 status_ = MIN(status_, rc_); \
323 if (test_cmp_magnitude) { \
324 rc_ = assert_equal_as_expr(fn(s0, s1, s0sz), \
325 s0[s0len] - s1[s0len], -1, \
326 "expected %d got %d\n"); \
327 status_ = MIN(status_, rc_); \
328 } \
329 rc_ = assert_positive_as_expr(fn(s1, s0, s0sz), -1, "\n"); \
330 status_ = MIN(status_, rc_); \
331 if (test_cmp_magnitude) { \
332 rc_ = assert_equal_as_expr(fn(s1, s0, s0sz), \
333 s1[s0len] - s0[s0len], -1, \
334 "expected %d got %d\n"); \
335 status_ = MIN(status_, rc_); \
336 } \
337 \
338 rc_ = assert_positive_as_expr(fn(s1, s2, s1sz), -1, "\n"); \
339 status_ = MIN(status_, rc_); \
340 if (test_cmp_magnitude) { \
341 rc_ = assert_equal_as_expr(fn(s1, s2, s2sz), \
342 s1[s2len] - s2[s2len], -1, \
343 "expected %d got %d\n"); \
344 status_ = MIN(status_, rc_); \
345 } \
346 rc_ = assert_positive_as_expr(fn(s1, s2, s1len), -1, "\n"); \
347 status_ = MIN(status_, rc_); \
348 if (test_cmp_magnitude) { \
349 rc_ = assert_equal_as_expr( \
350 fn(s1, s2, s2len), \
351 s1[s2len - 1] - s2[s2len - 1], -1, \
352 "expected %d got %d\n"); \
353 status_ = MIN(status_, rc_); \
354 } \
355 if (invert_sign_errors) \
356 rc_ = assert_positive_as_expr(fn(s2, s1, s1sz), -1, \
357 "\n"); \
358 else \
359 rc_ = assert_negative_as_expr(fn(s2, s1, s1sz), -1, \
360 "\n"); \
361 status_ = MIN(status_, rc_); \
362 if (test_cmp_magnitude) { \
363 rc_ = assert_equal_as_expr(fn(s2, s1, s1sz), \
364 s2[s2len] - s1[s2len], -1, \
365 "expected %d got %d\n"); \
366 status_ = MIN(status_, rc_); \
367 } \
368 \
369 rc_ = assert_zero_as_expr(fn(s1, s2, s2len), -1, "\n"); \
370 status_ = MIN(status_, rc_); \
371 rc_ = assert_positive_as_expr(fn(s1, s2, s2sz), -1, "\n"); \
372 status_ = MIN(status_, rc_); \
373 if (test_cmp_magnitude) { \
374 rc_ = assert_equal_as_expr(fn(s1, s2, s2sz), \
375 s1[s2len] - s2[s2len], -1, \
376 "expected %d got %d\n"); \
377 status_ = MIN(status_, rc_); \
378 } \
379 \
380 if (invert_sign_errors) \
381 rc_ = assert_positive_as_expr(fn(s2, s3, s2sz), -1, \
382 "\n"); \
383 else \
384 rc_ = assert_negative_as_expr(fn(s2, s3, s2sz), -1, \
385 "\n"); \
386 status_ = MIN(status_, rc_); \
387 rc_ = assert_equal_as_expr(fn(s2, s3, s2sz), \
388 s2[s2len - 1] - s3[s2len - 1], -1, \
389 "expected %d got %d\n"); \
390 status_ = MIN(status_, rc_); \
391 rc_ = assert_equal_as_expr(fn(s2, s3, s2len), \
392 s2[s2len - 1] - s3[s2len - 1], -1, \
393 "expected %d got %d\n"); \
394 status_ = MIN(status_, rc_); \
395 if (invert_sign_errors) \
396 rc_ = assert_positive_as_expr(fn(s2, s3, s2len), -1, \
397 "\n"); \
398 else \
399 rc_ = assert_negative_as_expr(fn(s2, s3, s2len), -1, \
400 "\n"); \
401 status_ = MIN(status_, rc_); \
402 rc_ = assert_zero_as_expr(fn(s2, s3, s2len - 1), -1, "\n"); \
403 status_ = MIN(status_, rc_); \
404 rc_ = assert_false_as_expr(fn(s1, s2, s2len), -1, "\n"); \
405 status_ = MIN(status_, rc_); \
406 \
407 if (invert_encoding_errors) \
408 rc_ = assert_negative_as_expr(fn(s4, s5, s4sz), -1, \
409 "\n"); \
410 else \
411 rc_ = assert_positive_as_expr(fn(s4, s5, s4sz), -1, \
412 "\n"); \
413 status_ = MIN(status_, rc_); \
414 \
415 if (status_ < 0) \
416 printf("%s failed\n", #fn); \
417 status_; \
418 })
419
420 static int
421 test_strncasecmp(void)
422 {
423 int status = 0;
424 int rc;
425
426 /*
427 * shim's strncasecmp
428 */
429 rc = test_strncasecmp_helper(shim_strncasecmp, true, false, false);
430 status = MIN(rc, status);
431
432 /*
433 * libc's strncasecmp
434 */
435 rc = test_strncasecmp_helper(strncasecmp, false, false, false);
436 status = MIN(rc, status);
437
438 return status;
439 }
440
441 #undef s0
442 #undef s0sz
443 #undef s0len
444 #undef s1
445 #undef s1sz
446 #undef s1len
447 #undef s2
448 #undef s2sz
449 #undef s2len
450 #undef s3
451 #undef s3sz
452 #undef s3len
453 #undef s4
454 #undef s4sz
455 #undef s4len
456 #undef s5
457 #undef s5sz
458 #undef s5len
459
460 /*
461 * copy-pasta from gnu-efi
462 */
463 static inline UINTN
464 gnuefi_strncmp (
465 IN CONST CHAR8 *s1,
466 IN CONST CHAR8 *s2,
467 IN UINTN len
468 )
469 {
470 while (*s1 && len) {
471 if (*s1 != *s2) {
472 break;
473 }
474
475 s1 += 1;
476 s2 += 1;
477 len -= 1;
478 }
479
480 return len ? *s1 - *s2 : 0;
481 }
482
483 /*
484 * This is still broken, and fails the test case as written on arm.
485 * We no longer use this, so we do not strictly need to run it.
486 */
487 #if !defined(__arm__) && !defined(__aarch64__)
488 static inline INTN
489 gnuefi_signed_strncmp (
490 IN CONST CHAR8 *s1,
491 IN CONST CHAR8 *s2,
492 IN UINTN len
493 )
494 {
495 while (*s1 && len) {
496 if (*s1 != *s2) {
497 break;
498 }
499
500 s1 += 1;
501 s2 += 1;
502 len -= 1;
503 }
504
505 return len ? *s1 - *s2 : 0;
506 }
507 #endif
508
509 static inline INTN
510 gnuefi_good_strncmp (
511 IN CONST CHAR8 *s1p,
512 IN CONST CHAR8 *s2p,
513 IN UINTN len
514 )
515 {
516 CONST UINT8 *s1 = (CONST UINT8 *)s1p;
517 CONST UINT8 *s2 = (CONST UINT8 *)s2p;
518
519 while (*s1 && len) {
520 if (*s1 != *s2) {
521 break;
522 }
523
524 s1 += 1;
525 s2 += 1;
526 len -= 1;
527 }
528
529 return len ? *s1 - *s2 : 0;
530 }
531
532 /*
533 * these are constants so that the failures are readable if you get
534 * it wrong.
535 */
536 #define s0 "sbat,"
537 #define s0sz 6
538 #define s0len 5
539 #define s1 "sbat,1,2021030218"
540 #define s1sz 18
541 #define s1len 17
542 #define s2 "sbat,1,20210302"
543 #define s2sz 16
544 #define s2len 15
545 #define s3 "sbat,1,20210303"
546 #define s3sz 16
547 #define s3len 15
548 #define s4 "sbat\314\234\014,"
549 #define s4sz 9
550 #define s4len 8
551 /*
552 * same as s4 but with a UTF8 encoding error; one bit is cleared.
553 */
554 #define s5 "sbat\314\034\014,"
555 #define s5sz 9
556 #define s5len 8
557
558 #define test_strncmp_helper(fn, test_cmp_magnitude, invert_sign_errors, \
559 invert_encoding_errors) \
560 ({ \
561 printf("testing %s\n", #fn); \
562 int status_ = 0, rc_; \
563 \
564 rc_ = assert_zero_as_expr(fn(s0, s0, s0len), -1, "\n"); \
565 status_ = MIN(status_, rc_); \
566 rc_ = assert_zero_as_expr(fn(s0, s0, s0sz), -1, "\n"); \
567 status_ = MIN(status_, rc_); \
568 \
569 rc_ = assert_zero_as_expr(fn(s0, s1, s0len), -1, "\n"); \
570 status_ = MIN(status_, rc_); \
571 if (invert_sign_errors) \
572 rc_ = assert_positive_as_expr(fn(s0, s1, s0sz), -1, \
573 "\n"); \
574 else \
575 rc_ = assert_negative_as_expr(fn(s0, s1, s0sz), -1, \
576 "\n"); \
577 status_ = MIN(status_, rc_); \
578 if (test_cmp_magnitude) { \
579 rc_ = assert_equal_as_expr(fn(s0, s1, s0sz), \
580 s0[s0len] - s1[s0len], -1, \
581 "expected %d got %d\n"); \
582 status_ = MIN(status_, rc_); \
583 } \
584 rc_ = assert_positive_as_expr(fn(s1, s0, s0sz), -1, "\n"); \
585 status_ = MIN(status_, rc_); \
586 if (test_cmp_magnitude) { \
587 rc_ = assert_equal_as_expr(fn(s1, s0, s0sz), \
588 s1[s0len] - s0[s0len], -1, \
589 "expected %d got %d\n"); \
590 status_ = MIN(status_, rc_); \
591 } \
592 \
593 rc_ = assert_positive_as_expr(fn(s1, s2, s1sz), -1, "\n"); \
594 status_ = MIN(status_, rc_); \
595 if (test_cmp_magnitude) { \
596 rc_ = assert_equal_as_expr(fn(s1, s2, s2sz), \
597 s1[s2len] - s2[s2len], -1, \
598 "expected %d got %d\n"); \
599 status_ = MIN(status_, rc_); \
600 } \
601 rc_ = assert_positive_as_expr(fn(s1, s2, s1len), -1, "\n"); \
602 status_ = MIN(status_, rc_); \
603 if (test_cmp_magnitude) { \
604 rc_ = assert_equal_as_expr( \
605 fn(s1, s2, s2len), \
606 s1[s2len - 1] - s2[s2len - 1], -1, \
607 "expected %d got %d\n"); \
608 status_ = MIN(status_, rc_); \
609 } \
610 if (invert_sign_errors) \
611 rc_ = assert_positive_as_expr(fn(s2, s1, s1sz), -1, \
612 "\n"); \
613 else \
614 rc_ = assert_negative_as_expr(fn(s2, s1, s1sz), -1, \
615 "\n"); \
616 status_ = MIN(status_, rc_); \
617 if (test_cmp_magnitude) { \
618 rc_ = assert_equal_as_expr(fn(s2, s1, s1sz), \
619 s2[s2len] - s1[s2len], -1, \
620 "expected %d got %d\n"); \
621 status_ = MIN(status_, rc_); \
622 } \
623 \
624 rc_ = assert_zero_as_expr(fn(s1, s2, s2len), -1, "\n"); \
625 status_ = MIN(status_, rc_); \
626 rc_ = assert_positive_as_expr(fn(s1, s2, s2sz), -1, "\n"); \
627 status_ = MIN(status_, rc_); \
628 if (test_cmp_magnitude) { \
629 rc_ = assert_equal_as_expr(fn(s1, s2, s2sz), \
630 s1[s2len] - s2[s2len], -1, \
631 "expected %d got %d\n"); \
632 status_ = MIN(status_, rc_); \
633 } \
634 \
635 if (invert_sign_errors) \
636 rc_ = assert_positive_as_expr(fn(s2, s3, s2sz), -1, \
637 "\n"); \
638 else \
639 rc_ = assert_negative_as_expr(fn(s2, s3, s2sz), -1, \
640 "\n"); \
641 status_ = MIN(status_, rc_); \
642 if (test_cmp_magnitude) { \
643 rc_ = assert_equal_as_expr( \
644 fn(s2, s3, s2sz), \
645 s2[s2len - 1] - s3[s2len - 1], -1, \
646 "expected %d got %d\n"); \
647 status_ = MIN(status_, rc_); \
648 rc_ = assert_equal_as_expr( \
649 fn(s2, s3, s2len), \
650 s2[s2len - 1] - s3[s2len - 1], -1, \
651 "expected %d got %d\n"); \
652 status_ = MIN(status_, rc_); \
653 } \
654 if (invert_sign_errors) \
655 rc_ = assert_positive_as_expr(fn(s2, s3, s2len), -1, \
656 "\n"); \
657 else \
658 rc_ = assert_negative_as_expr(fn(s2, s3, s2len), -1, \
659 "\n"); \
660 status_ = MIN(status_, rc_); \
661 rc_ = assert_zero_as_expr(fn(s2, s3, s2len - 1), -1, "\n"); \
662 status_ = MIN(status_, rc_); \
663 rc_ = assert_false_as_expr(fn(s1, s2, s2len), -1, "\n"); \
664 status_ = MIN(status_, rc_); \
665 \
666 if (invert_encoding_errors) \
667 rc_ = assert_negative_as_expr(fn(s4, s5, s4sz), -1, \
668 "\n"); \
669 else \
670 rc_ = assert_positive_as_expr(fn(s4, s5, s4sz), -1, \
671 "\n"); \
672 status_ = MIN(status_, rc_); \
673 \
674 if (status_ < 0) \
675 printf("%s failed\n", #fn); \
676 status_; \
677 })
678
679 static int
680 test_strncmp(void)
681 {
682 int status = 0;
683 int rc;
684
685 /*
686 * shim's strncmp
687 */
688 rc = test_strncmp_helper(shim_strncmp, true, false, false);
689 status = MIN(rc, status);
690
691 /*
692 * libc's strncmp
693 */
694 /*
695 * Deliberately not testing the difference between these two
696 * comparisons for the symbol named "strncmp":
697 * strncmp("b", "a", 1)
698 * strncmp("c", "a", 1)
699 * glibc, shim_strncmp(), and even the gnuefi ones will give you 1
700 * and 2, respectively, as will glibc's, but valgrind swaps in its
701 * own implementation, in case you're doing something that's both
702 * clever and dumb with the result, and it'll return 1 for both of
703 * them.
704 */
705 rc = test_strncmp_helper(strncmp, false, false, false);
706 status = MIN(rc, status);
707
708 /*
709 * gnu-efi's broken strncmpa
710 */
711 #pragma GCC diagnostic push
712 #pragma GCC diagnostic ignored "-Wtype-limits"
713 #pragma GCC diagnostic ignored "-Wsign-compare"
714 rc = test_strncmp_helper(gnuefi_strncmp, true, true, false);
715 status = MIN(rc, status);
716 #pragma GCC diagnostic pop
717
718 /*
719 * This is still broken, and fails the test case as written on arm.
720 * We no longer use this, so we do not strictly need to run it.
721 */
722 #if !defined(__arm__) && !defined(__aarch64__)
723 /*
724 * gnu-efi's broken strncmpa with the return type fixed
725 */
726 rc = test_strncmp_helper(gnuefi_signed_strncmp, true, false, true);
727 status = MIN(rc, status);
728 #endif
729
730 /*
731 * gnu-efi's strncmpa with the return type fixed and unsigned
732 * comparisons internally
733 */
734 rc = test_strncmp_helper(gnuefi_good_strncmp, true, false, false);
735 status = MIN(rc, status);
736
737 return status;
738 }
739
740 #undef s0
741 #undef s0sz
742 #undef s0len
743 #undef s1
744 #undef s1sz
745 #undef s1len
746 #undef s2
747 #undef s2sz
748 #undef s2len
749 #undef s3
750 #undef s3sz
751 #undef s3len
752 #undef s4
753 #undef s4sz
754 #undef s4len
755 #undef s5
756 #undef s5sz
757 #undef s5len
758
759 /*
760 * Put -Wshadow back how it was
761 */
762 #pragma GCC diagnostic pop
763
764 static int
765 test_strchr(void)
766 {
767 char s0[] = "abcbdbeb\0fbgb";
768
769 assert_equal_return(strchr(s0, 'a'), s0, -1, "got %p expected %p\n");
770 assert_equal_return(strchr(s0, 'b'), &s0[1], -1, "got %p expected %p\n");
771 assert_equal_return(strchr(&s0[1], 'b'), &s0[1], -1, "got %p expected %p\n");
772 assert_equal_return(strchr(&s0[2], 'b'), &s0[3], -1, "got %p expected %p\n");
773 assert_equal_return(strchr(&s0[4], 'b'), &s0[5], -1, "got %p expected %p\n");
774 assert_equal_return(strchr(&s0[6], 'b'), &s0[7], -1, "got %p expected %p\n");
775 assert_equal_return(strchr(&s0[8], 'b'), NULL, -1, "got %p expected %p\n");
776
777 assert_equal_return(shim_strchr(s0, 'a'), s0, -1, "got %p expected %p\n");
778 assert_equal_return(shim_strchr(s0, 'b'), &s0[1], -1, "got %p expected %p\n");
779 assert_equal_return(shim_strchr(&s0[1], 'b'), &s0[1], -1, "got %p expected %p\n");
780 assert_equal_return(shim_strchr(&s0[2], 'b'), &s0[3], -1, "got %p expected %p\n");
781 assert_equal_return(shim_strchr(&s0[4], 'b'), &s0[5], -1, "got %p expected %p\n");
782 assert_equal_return(shim_strchr(&s0[6], 'b'), &s0[7], -1, "got %p expected %p\n");
783 assert_equal_return(shim_strchr(&s0[8], 'b'), NULL, -1, "got %p expected %p\n");
784 return 0;
785 }
786
787 static int
788 test_stpcpy(void)
789 {
790 char s0[] = "0123456789abcdef";
791 char s1[] = "xxxxxxxxxxxxxxxx";
792 char *s;
793
794 s0[0xa] = 0;
795 assert_equal_return(stpcpy(s1, s0), &s1[0xa], -1, "got %p expected %p\n");
796 assert_zero_return(memcmp(s0, s1, 11), -1, "\n");
797 assert_zero_return(memcmp(&s1[11], "xxxxx", sizeof("xxxxx")), -1, "\n");
798
799 memset(s1, 'x', sizeof(s1));
800 s1[16] = 0;
801 assert_equal_return(shim_stpcpy(s1, s0), &s1[0xa], -1, "got %p expected %p\n");
802 assert_zero_return(memcmp(s0, s1, 11), -1, "\n");
803 assert_zero_return(memcmp(&s1[11], "xxxxx", sizeof("xxxxx")), -1, "\n");
804
805 return 0;
806 }
807
808 static int
809 test_strdup(void)
810 {
811 char s0[] = "0123456789abcdef";
812 char *s = NULL;
813
814 s = strdup(s0);
815 assert_equal_goto(strcmp(s0, s), 0, err, "\n");
816 free(s);
817
818 s = shim_strdup(s0);
819 assert_equal_goto(strcmp(s0, s), 0, err, "\n");
820 free(s);
821
822 return 0;
823 err:
824 if (s)
825 free(s);
826 return -1;
827 }
828
829 static int
830 test_strndup(void)
831 {
832 char s0[] = "0123456789abcdef";
833 char *s = NULL;
834
835 s = strndup(s0, 18);
836 assert_equal_goto(strcmp(s0, s), 0, err, "\n");
837 free(s);
838 s = strndup(s0, 15);
839 assert_positive_goto(strcmp(s0, s), err, "\n");
840 free(s);
841
842 s = shim_strndup(s0, 18);
843 assert_equal_goto(strcmp(s0, s), 0, err, "\n");
844 free(s);
845 s = strndup(s0, 15);
846 assert_positive_goto(shim_strcmp(s0, s), err, "\n");
847 free(s);
848
849 return 0;
850 err:
851 if (s)
852 free(s);
853 return -1;
854 }
855
856 static int
857 test_strchrnul_helper(__typeof__(strchrnul) fn)
858 {
859 const char s0[] = "abcd\0fghi";
860
861 assert_equal_return(fn(s0, 'a'), &s0[0], -1, "got %p expected %p\n");
862 assert_equal_return(fn(s0, 'd'), &s0[3], -1, "got %p expected %p\n");
863 assert_equal_return(fn(s0, '\000'), &s0[4], -1, "got %p expected %p\n");
864 assert_equal_return(fn(s0, 'i'), &s0[4], -1, "got %p expected %p\n");
865
866 return 0;
867 }
868
869 static int
870 test_strchrnul(void)
871 {
872 const char s0[] = "abcd\0fghi";
873
874 assert_equal_return(test_strchrnul_helper(shim_strchrnul),
875 test_strchrnul_helper(strchrnul),
876 -1, "got %d expected %d\n");
877
878 assert_equal_return(strnchrnul(s0, 0, 'b'), &s0[0], -1, "got %p expected %p\n");
879 assert_equal_return(strnchrnul(s0, -1, 'b'), &s0[1], 1, "got %p expected %p\n");
880 assert_equal_return(strnchrnul(s0, 2, 'b'), &s0[1], -1, "got %p expected %p\n");
881 assert_equal_return(strnchrnul(s0, 4, 'f'), &s0[3], -1, "got %p expected %p\n");
882 assert_equal_return(strnchrnul(s0, 5, 'f'), &s0[4], -1, "got %p expected %p\n");
883 assert_equal_return(strnchrnul(s0, 8, 'f'), &s0[4], -1, "got %p expected %p\n");
884
885 assert_equal_return(strnchrnul(&s0[4], 1, 'f'), &s0[4], -1, "got %p expected %p\n");
886
887 return 0;
888 }
889
890 static int
891 test_strrchr(void) {
892 char s0[] = "abcbebfb";
893
894 assert_equal_return(shim_strrchr(s0, '\n'), NULL, -1, "got %p expected %p\n");
895 assert_equal_return(strrchr(s0, '\n'), NULL, -1, "got %p expected %p\n");
896 assert_equal_return(shim_strrchr(s0, 'b'), &s0[7], -1, "got %p expected %p\n");
897 assert_equal_return(strrchr(s0, 'b'), &s0[7], -1, "got %p expected %p\n");
898 assert_equal_return(shim_strrchr(s0, 'c'), &s0[2], -1, "got %p expected %p\n");
899 assert_equal_return(strrchr(s0, 'c'), &s0[2], -1, "got %p expected %p\n");
900
901 return 0;
902 }
903
904 static int
905 test_strcpy(void)
906 {
907 char s0[] = "0123456789abcdef\0000";
908 char s1[sizeof(s0)];
909
910 memset(s1, 0, sizeof(s1));
911 assert_equal_return(strcpy(s1, s0), s1, -1, "got %p expected %p\n");
912 assert_equal_return(strlen(s0), strlen(s1), -1, "got %d expected %d\n");
913
914 memset(s1, 0, sizeof(s1));
915 assert_equal_return(shim_strcpy(s1, s0), s1, -1, "got %p expected %p\n");
916 assert_equal_return(strlen(s0), strlen(s1), -1, "got %d expected %d\n");
917
918 memset(s1, 0, sizeof(s1));
919 assert_equal_return(shim_strcpy(s1, s0), s1, -1, "got %p expected %p\n");
920 assert_equal_return(strlen(s0), strlen(s1), -1, "got %d expected %d\n");
921
922 return 0;
923 }
924
925 static int
926 test_strncpy(void)
927 {
928 char s[] = "0123456789abcdef\0000";
929 char s0[4096+4096];
930 char *s1 = &s0[4096];
931
932 memset(s0, 0, sizeof(s0));
933 memcpy(s0, s, sizeof(s));
934
935 memset(s1, 0, 4096);
936 assert_equal_return(strncpy(s1, s0, 0), s1, -1, "got %p expected %p\n");
937 assert_equal_return(strlen(s1), 0, -1, "got %d expected %d\n");
938 memset(s1, 0, 4096);
939 assert_equal_return(shim_strncpy(s1, s0, 0), s1, -1, "got %p expected %p\n");
940 assert_equal_return(strlen(s1), 0, -1, "got %d expected %d\n");
941
942 memset(s1, 0, 4096);
943 assert_equal_return(strncpy(s1, s0, 1), s1, -1, "got %p expected %p\n");
944 assert_equal_return(strlen(s1), 1, -1, "got %d expected %d\n");
945 assert_equal_return(s1[0], s0[0], -1, "got %#02hhx, expected %#02hhx\n");
946 assert_equal_return(s0[1], '1', -1, "got %#02hhx, expected %#02hhx\n");
947 assert_equal_return(s1[1], '\0', -1, "got %#02hhx, expected %#02hhx\n");
948 memset(s1, 0, 4096);
949 assert_equal_return(shim_strncpy(s1, s0, 1), s1, -1, "got %p expected %p\n");
950 assert_equal_return(strlen(s1), 1, -1, "got %d expected %d\n");
951 assert_equal_return(s1[0], s0[0], -1, "got %#02hhx, expected %#02hhx\n");
952 assert_equal_return(s0[1], '1', -1, "got %#02hhx, expected %#02hhx\n");
953 assert_equal_return(s1[1], '\0', -1, "got %#02hhx, expected %#02hhx\n");
954
955 memset(s1, 0, 4096);
956 assert_equal_return(strncpy(s1, s0, 15), s1, -1, "got %p expected %p\n");
957 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
958 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
959 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
960 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
961 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
962 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
963 assert_equal_return(s1[15], '\000', -1, "got %#02hhx expected %02hhx\n");
964 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
965 assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
966 assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
967 memset(s1, 0, 4096);
968 assert_equal_return(shim_strncpy(s1, s0, 15), s1, -1, "got %p expected %p\n");
969 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
970 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
971 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
972 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
973 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
974 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
975 assert_equal_return(s1[15], '\000', -1, "got %#02hhx expected %02hhx\n");
976 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
977 assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
978 assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
979
980 memset(s1, 0, 4096);
981 assert_equal_return(strncpy(s1, s0, 16), s1, -1, "got %p expected %p\n");
982 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
983 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
984 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
985 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
986 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
987 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
988 assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
989 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
990 assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
991 assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
992 memset(s1, 0, 4096);
993 assert_equal_return(shim_strncpy(s1, s0, 16), s1, -1, "got %p expected %p\n");
994 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
995 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
996 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
997 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
998 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
999 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
1000 assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
1001 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1002 assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
1003 assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
1004
1005 memset(s1, 0, 4096);
1006 s1[17] = '0';
1007 s1[18] = '1';
1008 assert_equal_return(strncpy(s1, s0, 4096), s1, -1, "got %p expected %p\n");
1009 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
1010 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
1011 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1012 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
1013 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
1014 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
1015 assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
1016 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1017 assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
1018 assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
1019 memset(s1, 0, 4096);
1020 s1[17] = '0';
1021 s1[18] = '1';
1022 assert_equal_return(shim_strncpy(s1, s0, 4096), s1, -1, "got %p expected %p\n");
1023 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
1024 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
1025 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1026 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
1027 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
1028 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
1029 assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
1030 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1031 assert_equal_return(s1[17], '0', -1, "got %#02hhx expected %02hhx\n");
1032 assert_equal_return(s1[18], '1', -1, "got %#02hhx expected %02hhx\n");
1033
1034 return 0;
1035 }
1036
1037 static int
1038 test_strcat(void)
1039 {
1040 char s[] = "0123456789abcdef\0000";
1041 char s0[8192];
1042 char *s1 = &s0[4096];
1043 char *s2;
1044 char s3[] = "0123456789abcdef0123456789abcdef\000\000\000\000\000";
1045
1046 memset(s0, 0, 8192);
1047 memcpy(s0, s, sizeof(s));
1048
1049 memset(s1, 0, 4096);
1050 assert_equal_return(strcat(s1, s0), s1, -1, "got %p expected %p\n");
1051 /* For unknown reasons, gcc 4.8.5 gives us this here:
1052 * | In file included from shim.h:64:0,
1053 * | from test-str.c:14:
1054 * | test-str.c: In function 'test_strcat':
1055 * | include/test.h:85:10: warning: array subscript is below array bounds [-Warray-bounds]
1056 * | printf("%s:%d:got %lld, expected zero " fmt, __func__, \
1057 * | ^
1058 * | include/test.h:112:10: warning: array subscript is below array bounds [-Warray-bounds]
1059 * | printf("%s:%d:got %lld, expected < 0 " fmt, __func__, \
1060 * | ^
1061 *
1062 * This clearly isn't a useful error message, as it doesn't tell us
1063 * /anything about the problem/, but also it isn't reported on
1064 * later compilers, and it isn't clear that there's any problem
1065 * when examining these functions.
1066 *
1067 * I don't know.
1068 */
1069 #pragma GCC diagnostic push
1070 #pragma GCC diagnostic ignored "-Warray-bounds"
1071 assert_zero_return(strncmp(s1, s0, sizeof(s)-1), 0, -1, "\n");
1072 assert_negative_return(memcmp(s1, s0, sizeof(s)), 0, -1, "\n");
1073 #pragma GCC diagnostic pop
1074
1075 memset(s1, 0, 4096);
1076 assert_equal_return(strcat(s1, s0), s1, -1, "got %p expected %p\n");
1077 s2 = s1 + strlen(s1);
1078 assert_equal_return(s2, &s1[16], -1, "got %p expected %p\n");
1079 assert_equal_return(strcat(s2, s0), s2, -1, "got %p expected %p\n");
1080 assert_zero_return(strncmp(s1, s0, strlen(s)), -1, "got %p expected %p\n");
1081 assert_zero_return(strncmp(s2, s0, 2*(sizeof(s)-1)), -1, "\n");
1082 assert_positive_return(memcmp(s1, s0, 2*sizeof(s)-2), -1, "\n");
1083 assert_equal_return(memcmp(s1, s3, sizeof(s3)), 0, -1, "expected %d got %d\n");
1084
1085 return 0;
1086 }
1087
1088 static int
1089 test_strntoken_null(void) {
1090 bool ret;
1091 char *token = NULL;
1092 char state;
1093
1094 char *delims = alloca(3);
1095 memcpy(delims, ",.", 3);
1096
1097 ret = strntoken(NULL, 1, delims, &token, &state);
1098 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1099 return 0;
1100 }
1101
1102 static int
1103 test_strntoken_size_0(void)
1104 {
1105 const char s1[] = "abc,def,.,gh,";
1106 char s2[] = "abc,def,.,gh,";
1107 char *token = NULL;
1108 bool ret;
1109 size_t max;
1110 char *s = s2;
1111 size_t tokensz;
1112 char state;
1113
1114 ret = strntoken(s, 0, ",.", &token, &state);
1115 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1116 assert_equal_return(token, NULL, -1, "got %p expected %p\n");
1117 assert_equal_return(memcmp(s, "abc,def,.,gh,", sizeof(s2)), 0, 1, "got %d expected %d\n");
1118
1119 return 0;
1120 }
1121
1122 static int
1123 test_strntoken_empty_size_1(void)
1124 {
1125 char s1[] = "";
1126 char *s;
1127 bool ret;
1128 char *token = NULL;
1129 char *prevtok = NULL;
1130 size_t max;
1131 size_t tokensz;
1132 char state;
1133
1134 s = s1;
1135 max = 1;
1136
1137 ret = strntoken(s, max, ",.", &token, &state);
1138 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1139 assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
1140 prevtok = token;
1141
1142 tokensz = strlen(token) + 1;
1143 s += tokensz;
1144 max -= tokensz;
1145 assert_equal_return(s, &s1[1], -1, "got %p expected %p\n");
1146 assert_equal_return(max, 0, -1, "got %d expected %d\n");
1147
1148 ret = strntoken(s, max, ",.", &token, &state);
1149 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1150 assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
1151
1152 return 0;
1153 }
1154
1155 static int
1156 test_strntoken_size_1(void)
1157 {
1158 char s1[] = ",";
1159 char *s;
1160 bool ret;
1161 char *token = NULL;
1162 char *prevtok = NULL;
1163 size_t max;
1164 size_t tokensz;
1165 char state;
1166
1167 s = s1;
1168 max = 1;
1169
1170 ret = strntoken(s, max, ",.", &token, &state);
1171 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1172 assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
1173 prevtok = token;
1174
1175 tokensz = strlen(token) + 1;
1176 s += tokensz;
1177 max -= tokensz;
1178 assert_equal_return(s, &s1[1], -1, "got %p expected %p\n");
1179 assert_equal_return(max, 0, -1, "got %d expected %d\n");
1180
1181 ret = strntoken(s, max, ",.", &token, &state);
1182 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1183 assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
1184 assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
1185
1186 return 0;
1187 }
1188
1189 static int
1190 test_strntoken_size_2(void)
1191 {
1192 char s1[] = ",";
1193 char *s;
1194 bool ret;
1195 char *token = NULL;
1196 char *prevtok = NULL;
1197 size_t max;
1198 size_t tokensz;
1199 char state;
1200
1201 s = s1;
1202 max = 2;
1203
1204 ret = strntoken(s, max, ",.", &token, &state);
1205 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1206 assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
1207
1208 tokensz = strlen(token) + 1;
1209 s += tokensz;
1210 max -= tokensz;
1211 assert_equal_return(s, &s1[1], -1, "got %p expected %p\n");
1212 assert_equal_return(max, 1, -1, "got %d expected %d\n");
1213
1214 ret = strntoken(s, max, ",.", &token, &state);
1215 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1216 assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
1217 prevtok = token;
1218
1219 tokensz = strlen(token) + 1;
1220 s += tokensz;
1221 max -= tokensz;
1222 assert_equal_return(s, &s1[2], -1, "got %p expected %p\n");
1223 assert_equal_return(max, 0, -1, "got %d expected %d\n");
1224
1225 ret = strntoken(s, max, ",.", &token, &state);
1226 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1227 assert_equal_return(token, prevtok, -1, "got %#hhx expected %#hhx\n");
1228
1229 return 0;
1230 }
1231
1232 static int
1233 test_strntoken_no_ascii_nul(void)
1234 {
1235 const char s1[] = "abc,def,.,gh,";
1236 char s2[] = "abc,def,.,gh,";
1237 char *token = NULL;
1238 bool ret;
1239 size_t max;
1240 char *s = s2;
1241 size_t tokensz;
1242 char state;
1243
1244 s = s2;
1245 max = sizeof(s2) - 1;
1246 assert_equal_return(max, 13, -1, "got %d expected %d\n");
1247 /*
1248 * s="abc,def,.,gh," -> "abc\0def,.,gh,"
1249 * ^ token
1250 */
1251 ret = strntoken(s, max, ",.", &token, &state);
1252 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1253 assert_equal_return(token, s, -1, "got %p expected %p\n");
1254 assert_equal_return(s[2], 'c', -1, "got %#hhx expected %#hhx\n");
1255 assert_equal_return(s[3], '\0', -1, "got %#hhx expected %#hhx\n");
1256 assert_equal_return(s[4], 'd', -1, "got %#hhx expected %#hhx\n");
1257
1258 tokensz = strnlen(token, max) + 1;
1259 s += tokensz;
1260 max -= tokensz;
1261 assert_equal_return(max, 9, -1, "got %d expected %d\n");
1262
1263 /*
1264 * s="def,.,gh," -> "def\0.,gh,"
1265 * ^ token
1266 */
1267 ret = strntoken(s, max, ",.", &token, &state);
1268 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1269 assert_equal_return(token, s, -1, "got %p expected %p\n");
1270 assert_equal_return(s[2], 'f', -1, "got %#hhx expected %#hhx\n");
1271 assert_equal_return(s[3], '\0', -1, "got %#hhx expected %#hhx\n");
1272 assert_equal_return(s[4], '.', -1, "got %#hhx expected %#hhx\n");
1273
1274 tokensz = strnlen(token, max) + 1;
1275 s += tokensz;
1276 max -= tokensz;
1277 assert_equal_return(max, 5, -1, "got %d expected %d\n");
1278
1279 /*
1280 * s=".,gh," -> "\0,gh,"
1281 * ^ token
1282 */
1283 ret = strntoken(s, max, ",.", &token, &state);
1284 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1285 assert_equal_return(token, s, -1, "got %p expected %p\n");
1286 assert_equal_return(s[0], '\0', -1, "got %#hhx expected %#hhx\n");
1287 assert_equal_return(s[1], ',', -1, "got %#hhx expected %#hhx\n");
1288
1289 tokensz = strnlen(token, max) + 1;
1290 s += tokensz;
1291 max -= tokensz;
1292 assert_equal_return(max, 4, -1, "got %d expected %d\n");
1293
1294 /*
1295 * s=",gh," -> "\0gh,"
1296 * ^ token
1297 */
1298 ret = strntoken(s, max, ",.", &token, &state);
1299 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1300 assert_equal_return(token, s, -1, "got %p expected %p\n");
1301 assert_equal_return(s[0], '\0', -1, "got %#hhx expected %#hhx\n");
1302 assert_equal_return(s[1], 'g', -1, "got %#hhx expected %#hhx\n");
1303
1304 tokensz = strnlen(token, max) + 1;
1305 s += tokensz;
1306 max -= tokensz;
1307 assert_equal_return(max, 3, -1, "got %d expected %d\n");
1308
1309 /*
1310 * s="gh," -> "gh\0"
1311 * ^ token
1312 */
1313 ret = strntoken(s, max, ",.", &token, &state);
1314 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1315 assert_equal_return(token, s, -1, "got %p expected %p\n");
1316 assert_equal_return(s[0], 'g', -1, "got %#hhx expected %#hhx\n");
1317 assert_equal_return(s[1], 'h', -1, "got %#hhx expected %#hhx\n");
1318 assert_equal_return(s[2], '\0', -1, "got %#hhx expected %#hhx\n");
1319
1320 tokensz = strnlen(token, max) + 1;
1321 s += tokensz;
1322 max -= tokensz;
1323 assert_equal_return(max, 0, -1, "got %d expected %d\n");
1324
1325 char *prevtok = token;
1326
1327 /*
1328 * s="" -> ""
1329 * ^ token, but max is 0
1330 */
1331 ret = strntoken(s, max, ",.", &token, &state);
1332 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1333 assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
1334 assert_equal_return(s[0], '\0', -1, "got %#hhx expected %#hhx\n");
1335
1336 s[0] = 'x';
1337 ret = strntoken(s, max, ",.", &token, &state);
1338 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1339 assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
1340 assert_equal_return(s[0], 'x', -1, "got %#hhx expected %#hhx\n");
1341
1342 return 0;
1343 }
1344
1345 static int
1346 test_strntoken_with_ascii_nul(void)
1347 {
1348 const char s1[] = "abc,def,.,gh,";
1349 char s2[] = "abc,def,.,gh,";
1350 char *token = NULL;
1351 bool ret;
1352 size_t max;
1353 char *s = s2;
1354 size_t tokensz;
1355 char s3[] = "abc,def,.,gh,";
1356 char state;
1357
1358 s = s2;
1359 max = sizeof(s2);
1360 assert_equal_return(max, 14, 1, "got %d expected %d\n");
1361 /*
1362 * s="abc,def,.,gh," -> "abc\0def,.,gh,"
1363 * ^ token
1364 */
1365 ret = strntoken(s, max, ",.", &token, &state);
1366 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1367 assert_equal_return(s[2], 'c', 1, "got %#hhx expected %#hhx\n");
1368 assert_equal_return(s[3], '\0', 1, "got %#hhx expected %#hhx\n");
1369 assert_equal_return(s[4], 'd', 1, "got %#hhx expected %#hhx\n");
1370
1371 tokensz = strnlen(token, max) + 1;
1372 s += tokensz;
1373 max -= tokensz;
1374 assert_equal_return(max, 10, 1, "got %d expected %d\n");
1375
1376 /*
1377 * s="def,.,gh," -> "def\0.,gh,"
1378 * ^ token
1379 */
1380 ret = strntoken(s, max, ",.", &token, &state);
1381 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1382 assert_equal_return(token, s, 1, "got %p expected %p\n");
1383 assert_equal_return(s[2], 'f', 1, "got %#hhx expected %#hhx\n");
1384 assert_equal_return(s[3], '\0', 1, "got %#hhx expected %#hhx\n");
1385 assert_equal_return(s[4], '.', 1, "got %#hhx expected %#hhx\n");
1386
1387 tokensz = strnlen(token, max) + 1;
1388 s += tokensz;
1389 max -= tokensz;
1390 assert_equal_return(max, 6, 1, "got %d expected %d\n");
1391
1392 /*
1393 * s=".,gh," -> "\0,gh,"
1394 * ^ token
1395 */
1396 ret = strntoken(s, max, ",.", &token, &state);
1397 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1398 assert_equal_return(token, s, 1, "got %p expected %p\n");
1399 assert_equal_return(s[0], '\0', 1, "got %#hhx expected %#hhx\n");
1400 assert_equal_return(s[1], ',', 1, "got %#hhx expected %#hhx\n");
1401
1402 tokensz = strnlen(token, max) + 1;
1403 s += tokensz;
1404 max -= tokensz;
1405 assert_equal_return(max, 5, 1, "got %d expected %d\n");
1406
1407 /*
1408 * s=",gh," -> "\0gh,"
1409 * ^ token
1410 */
1411 ret = strntoken(s, max, ",.", &token, &state);
1412 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1413 assert_equal_return(token, s, 1, "got %p expected %p\n");
1414 assert_equal_return(s[0], '\0', 1, "got %#hhx expected %#hhx\n");
1415 assert_equal_return(s[1], 'g', 1, "got %#hhx expected %#hhx\n");
1416
1417 tokensz = strnlen(token, max) + 1;
1418 s += tokensz;
1419 max -= tokensz;
1420 assert_equal_return(max, 4, 1, "got %d expected %d\n");
1421
1422 /*
1423 * s="gh," -> "gh\0"
1424 * ^ token
1425 */
1426 ret = strntoken(s, max, ",.", &token, &state);
1427 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1428 assert_equal_return(token, s, 1, "got %p expected %p\n");
1429 assert_equal_return(s[0], 'g', 1, "got %#hhx expected %#hhx\n");
1430 assert_equal_return(s[1], 'h', 1, "got %#hhx expected %#hhx\n");
1431 assert_equal_return(s[2], '\0', 1, "got %#hhx expected %#hhx\n");
1432
1433 tokensz = strnlen(token, max) + 1;
1434 s += tokensz;
1435 max -= tokensz;
1436 assert_equal_return(max, 1, 1, "got %d expected %d\n");
1437
1438 /*
1439 * s="" -> ""
1440 * ^ token, max is 1
1441 */
1442 ret = strntoken(s, max, ",.", &token, &state);
1443 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1444 assert_equal_return(token, s, 1, "got %p expected %p\n");
1445 assert_equal_return(s[0], '\0', 1, "got %#hhx expected %#hhx\n");
1446
1447 char *prevtok = token;
1448 tokensz = strnlen(token, max) + 1;
1449 s += tokensz;
1450 max -= tokensz;
1451 assert_equal_return(max, 0, 1, "got %d expected %d\n");
1452
1453 /*
1454 * s="" -> ""
1455 * ^ token, max is 0
1456 */
1457 ret = strntoken(s, max, ",.", &token, &state);
1458 assert_equal_return(ret, false, 1, "got %d expected %d\n");
1459 assert_equal_return(token, prevtok, 1, "got %p expected %p\n");
1460
1461 return 0;
1462 }
1463
1464 int
1465 main(void)
1466 {
1467 int status = 0;
1468 test(test_strlen);
1469 test(test_strnlen);
1470 test(test_strcmp);
1471 test(test_strncmp);
1472 test(test_strcasecmp);
1473 test(test_strncasecmp);
1474 test(test_strrchr);
1475 test(test_strcpy);
1476 test(test_strncpy);
1477 test(test_strcat);
1478 test(test_stpcpy);
1479 test(test_strdup);
1480 test(test_strndup);
1481 test(test_strchr);
1482 test(test_strchrnul);
1483 test(test_strntoken_null);
1484 test(test_strntoken_size_0);
1485 test(test_strntoken_empty_size_1);
1486 test(test_strntoken_size_1);
1487 test(test_strntoken_size_2);
1488 test(test_strntoken_no_ascii_nul);
1489 test(test_strntoken_with_ascii_nul);
1490 return status;
1491 }
1492
1493 // vim:fenc=utf-8:tw=75:noet