]> git.proxmox.com Git - efi-boot-shim.git/blame - test-str.c
Tweak the UUID handling to be clearer
[efi-boot-shim.git] / test-str.c
CommitLineData
031e5cce
SM
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
18static int
19test_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
32static int
33test_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
128static int
129test_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
237static int
238test_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
420static int
421test_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 */
463static inline UINTN
464gnuefi_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__)
488static inline INTN
489gnuefi_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
509static inline INTN
510gnuefi_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
679static int
680test_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
764static int
765test_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
787static int
788test_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
808static int
809test_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;
823err:
824 if (s)
825 free(s);
826 return -1;
827}
828
829static int
830test_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;
850err:
851 if (s)
852 free(s);
853 return -1;
854}
855
856static int
857test_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
869static int
870test_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
890static int
891test_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
904static int
905test_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
925static int
926test_strncpy(void)
927{
928 char s[] = "0123456789abcdef\0000";
e6ace38a
SM
929 char s0[4096];
930 char s1[4096];
031e5cce
SM
931
932 memset(s0, 0, sizeof(s0));
933 memcpy(s0, s, sizeof(s));
e6ace38a
SM
934#if __GNUC_PREREQ(8, 1)
935# pragma GCC diagnostic push
936# pragma GCC diagnostic ignored "-Wstringop-truncation"
937#endif
031e5cce
SM
938 memset(s1, 0, 4096);
939 assert_equal_return(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 memset(s1, 0, 4096);
942 assert_equal_return(shim_strncpy(s1, s0, 0), s1, -1, "got %p expected %p\n");
943 assert_equal_return(strlen(s1), 0, -1, "got %d expected %d\n");
944
945 memset(s1, 0, 4096);
946 assert_equal_return(strncpy(s1, s0, 1), s1, -1, "got %p expected %p\n");
947 assert_equal_return(strlen(s1), 1, -1, "got %d expected %d\n");
948 assert_equal_return(s1[0], s0[0], -1, "got %#02hhx, expected %#02hhx\n");
949 assert_equal_return(s0[1], '1', -1, "got %#02hhx, expected %#02hhx\n");
950 assert_equal_return(s1[1], '\0', -1, "got %#02hhx, expected %#02hhx\n");
951 memset(s1, 0, 4096);
952 assert_equal_return(shim_strncpy(s1, s0, 1), s1, -1, "got %p expected %p\n");
953 assert_equal_return(strlen(s1), 1, -1, "got %d expected %d\n");
954 assert_equal_return(s1[0], s0[0], -1, "got %#02hhx, expected %#02hhx\n");
955 assert_equal_return(s0[1], '1', -1, "got %#02hhx, expected %#02hhx\n");
956 assert_equal_return(s1[1], '\0', -1, "got %#02hhx, expected %#02hhx\n");
957
958 memset(s1, 0, 4096);
959 assert_equal_return(strncpy(s1, s0, 15), s1, -1, "got %p expected %p\n");
960 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
961 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
962 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
963 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
964 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
965 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
966 assert_equal_return(s1[15], '\000', -1, "got %#02hhx expected %02hhx\n");
967 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
968 assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
969 assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
970 memset(s1, 0, 4096);
971 assert_equal_return(shim_strncpy(s1, s0, 15), s1, -1, "got %p expected %p\n");
972 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
973 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
974 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
975 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
976 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
977 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
978 assert_equal_return(s1[15], '\000', -1, "got %#02hhx expected %02hhx\n");
979 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
980 assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
981 assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
982
983 memset(s1, 0, 4096);
984 assert_equal_return(strncpy(s1, s0, 16), s1, -1, "got %p expected %p\n");
985 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
986 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
987 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
988 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
989 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
990 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
991 assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
992 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
993 assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
994 assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
995 memset(s1, 0, 4096);
996 assert_equal_return(shim_strncpy(s1, s0, 16), s1, -1, "got %p expected %p\n");
997 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
998 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
999 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1000 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
1001 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
1002 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
1003 assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
1004 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1005 assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
1006 assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
1007
1008 memset(s1, 0, 4096);
1009 s1[17] = '0';
1010 s1[18] = '1';
1011 assert_equal_return(strncpy(s1, s0, 4096), s1, -1, "got %p expected %p\n");
1012 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
1013 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
1014 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1015 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
1016 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
1017 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
1018 assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
1019 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1020 assert_equal_return(s1[17], '\000', -1, "got %#02hhx expected %02hhx\n");
1021 assert_equal_return(s1[18], '\000', -1, "got %#02hhx expected %02hhx\n");
1022 memset(s1, 0, 4096);
1023 s1[17] = '0';
1024 s1[18] = '1';
1025 assert_equal_return(shim_strncpy(s1, s0, 4096), s1, -1, "got %p expected %p\n");
1026 assert_equal_return(s0[14], 'e', -1, "got %#02hhx expected %02hhx\n");
1027 assert_equal_return(s0[15], 'f', -1, "got %#02hhx expected %02hhx\n");
1028 assert_equal_return(s0[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1029 assert_equal_return(s0[17], '0', -1, "got %#02hhx expected %02hhx\n");
1030 assert_equal_return(s0[18], '\000', -1, "got %#02hhx expected %02hhx\n");
1031 assert_equal_return(s1[14], 'e', -1, "got %#02hhx expected %02hhx\n");
1032 assert_equal_return(s1[15], 'f', -1, "got %#02hhx expected %02hhx\n");
1033 assert_equal_return(s1[16], '\000', -1, "got %#02hhx expected %02hhx\n");
1034 assert_equal_return(s1[17], '0', -1, "got %#02hhx expected %02hhx\n");
1035 assert_equal_return(s1[18], '1', -1, "got %#02hhx expected %02hhx\n");
e6ace38a
SM
1036#if __GNUC_PREREQ(8, 1)
1037# pragma GCC diagnostic pop
1038#endif
031e5cce
SM
1039 return 0;
1040}
1041
1042static int
1043test_strcat(void)
1044{
1045 char s[] = "0123456789abcdef\0000";
e6ace38a
SM
1046 char s0[4096];
1047 char s1[4096];
031e5cce
SM
1048 char *s2;
1049 char s3[] = "0123456789abcdef0123456789abcdef\000\000\000\000\000";
1050
e6ace38a 1051 memset(s0, 0, sizeof(s0));
031e5cce
SM
1052 memcpy(s0, s, sizeof(s));
1053
1054 memset(s1, 0, 4096);
1055 assert_equal_return(strcat(s1, s0), s1, -1, "got %p expected %p\n");
1056 /* For unknown reasons, gcc 4.8.5 gives us this here:
1057 * | In file included from shim.h:64:0,
1058 * | from test-str.c:14:
1059 * | test-str.c: In function 'test_strcat':
1060 * | include/test.h:85:10: warning: array subscript is below array bounds [-Warray-bounds]
1061 * | printf("%s:%d:got %lld, expected zero " fmt, __func__, \
1062 * | ^
1063 * | include/test.h:112:10: warning: array subscript is below array bounds [-Warray-bounds]
1064 * | printf("%s:%d:got %lld, expected < 0 " fmt, __func__, \
1065 * | ^
1066 *
1067 * This clearly isn't a useful error message, as it doesn't tell us
1068 * /anything about the problem/, but also it isn't reported on
1069 * later compilers, and it isn't clear that there's any problem
1070 * when examining these functions.
1071 *
1072 * I don't know.
1073 */
1074#pragma GCC diagnostic push
8529e0f7 1075#pragma GCC diagnostic ignored "-Warray-bounds"
031e5cce
SM
1076 assert_zero_return(strncmp(s1, s0, sizeof(s)-1), 0, -1, "\n");
1077 assert_negative_return(memcmp(s1, s0, sizeof(s)), 0, -1, "\n");
1078#pragma GCC diagnostic pop
1079
1080 memset(s1, 0, 4096);
1081 assert_equal_return(strcat(s1, s0), s1, -1, "got %p expected %p\n");
1082 s2 = s1 + strlen(s1);
1083 assert_equal_return(s2, &s1[16], -1, "got %p expected %p\n");
1084 assert_equal_return(strcat(s2, s0), s2, -1, "got %p expected %p\n");
1085 assert_zero_return(strncmp(s1, s0, strlen(s)), -1, "got %p expected %p\n");
1086 assert_zero_return(strncmp(s2, s0, 2*(sizeof(s)-1)), -1, "\n");
1087 assert_positive_return(memcmp(s1, s0, 2*sizeof(s)-2), -1, "\n");
1088 assert_equal_return(memcmp(s1, s3, sizeof(s3)), 0, -1, "expected %d got %d\n");
1089
1090 return 0;
1091}
1092
1093static int
1094test_strntoken_null(void) {
1095 bool ret;
1096 char *token = NULL;
1097 char state;
1098
1099 char *delims = alloca(3);
1100 memcpy(delims, ",.", 3);
1101
1102 ret = strntoken(NULL, 1, delims, &token, &state);
1103 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1104 return 0;
1105}
1106
1107static int
1108test_strntoken_size_0(void)
1109{
1110 const char s1[] = "abc,def,.,gh,";
1111 char s2[] = "abc,def,.,gh,";
1112 char *token = NULL;
1113 bool ret;
1114 size_t max;
1115 char *s = s2;
1116 size_t tokensz;
1117 char state;
1118
1119 ret = strntoken(s, 0, ",.", &token, &state);
1120 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1121 assert_equal_return(token, NULL, -1, "got %p expected %p\n");
1122 assert_equal_return(memcmp(s, "abc,def,.,gh,", sizeof(s2)), 0, 1, "got %d expected %d\n");
1123
1124 return 0;
1125}
1126
1127static int
1128test_strntoken_empty_size_1(void)
1129{
1130 char s1[] = "";
1131 char *s;
1132 bool ret;
1133 char *token = NULL;
1134 char *prevtok = NULL;
1135 size_t max;
1136 size_t tokensz;
1137 char state;
1138
1139 s = s1;
1140 max = 1;
1141
1142 ret = strntoken(s, max, ",.", &token, &state);
1143 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1144 assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
1145 prevtok = token;
1146
1147 tokensz = strlen(token) + 1;
1148 s += tokensz;
1149 max -= tokensz;
1150 assert_equal_return(s, &s1[1], -1, "got %p expected %p\n");
1151 assert_equal_return(max, 0, -1, "got %d expected %d\n");
1152
1153 ret = strntoken(s, max, ",.", &token, &state);
1154 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1155 assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
1156
1157 return 0;
1158}
1159
1160static int
1161test_strntoken_size_1(void)
1162{
1163 char s1[] = ",";
1164 char *s;
1165 bool ret;
1166 char *token = NULL;
1167 char *prevtok = NULL;
1168 size_t max;
1169 size_t tokensz;
1170 char state;
1171
1172 s = s1;
1173 max = 1;
1174
1175 ret = strntoken(s, max, ",.", &token, &state);
1176 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1177 assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
1178 prevtok = token;
1179
1180 tokensz = strlen(token) + 1;
1181 s += tokensz;
1182 max -= tokensz;
1183 assert_equal_return(s, &s1[1], -1, "got %p expected %p\n");
1184 assert_equal_return(max, 0, -1, "got %d expected %d\n");
1185
1186 ret = strntoken(s, max, ",.", &token, &state);
1187 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1188 assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
1189 assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
1190
1191 return 0;
1192}
1193
1194static int
1195test_strntoken_size_2(void)
1196{
1197 char s1[] = ",";
1198 char *s;
1199 bool ret;
1200 char *token = NULL;
1201 char *prevtok = NULL;
1202 size_t max;
1203 size_t tokensz;
1204 char state;
1205
1206 s = s1;
1207 max = 2;
1208
1209 ret = strntoken(s, max, ",.", &token, &state);
1210 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1211 assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
1212
1213 tokensz = strlen(token) + 1;
1214 s += tokensz;
1215 max -= tokensz;
1216 assert_equal_return(s, &s1[1], -1, "got %p expected %p\n");
1217 assert_equal_return(max, 1, -1, "got %d expected %d\n");
1218
1219 ret = strntoken(s, max, ",.", &token, &state);
1220 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1221 assert_equal_return(token[0], '\0', -1, "got %#hhx expected %#hhx\n");
1222 prevtok = token;
1223
1224 tokensz = strlen(token) + 1;
1225 s += tokensz;
1226 max -= tokensz;
1227 assert_equal_return(s, &s1[2], -1, "got %p expected %p\n");
1228 assert_equal_return(max, 0, -1, "got %d expected %d\n");
1229
1230 ret = strntoken(s, max, ",.", &token, &state);
1231 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1232 assert_equal_return(token, prevtok, -1, "got %#hhx expected %#hhx\n");
1233
1234 return 0;
1235}
1236
1237static int
1238test_strntoken_no_ascii_nul(void)
1239{
1240 const char s1[] = "abc,def,.,gh,";
1241 char s2[] = "abc,def,.,gh,";
1242 char *token = NULL;
1243 bool ret;
1244 size_t max;
1245 char *s = s2;
1246 size_t tokensz;
1247 char state;
1248
1249 s = s2;
1250 max = sizeof(s2) - 1;
1251 assert_equal_return(max, 13, -1, "got %d expected %d\n");
1252 /*
1253 * s="abc,def,.,gh," -> "abc\0def,.,gh,"
1254 * ^ token
1255 */
1256 ret = strntoken(s, max, ",.", &token, &state);
1257 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1258 assert_equal_return(token, s, -1, "got %p expected %p\n");
1259 assert_equal_return(s[2], 'c', -1, "got %#hhx expected %#hhx\n");
1260 assert_equal_return(s[3], '\0', -1, "got %#hhx expected %#hhx\n");
1261 assert_equal_return(s[4], 'd', -1, "got %#hhx expected %#hhx\n");
1262
1263 tokensz = strnlen(token, max) + 1;
1264 s += tokensz;
1265 max -= tokensz;
1266 assert_equal_return(max, 9, -1, "got %d expected %d\n");
1267
1268 /*
1269 * s="def,.,gh," -> "def\0.,gh,"
1270 * ^ token
1271 */
1272 ret = strntoken(s, max, ",.", &token, &state);
1273 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1274 assert_equal_return(token, s, -1, "got %p expected %p\n");
1275 assert_equal_return(s[2], 'f', -1, "got %#hhx expected %#hhx\n");
1276 assert_equal_return(s[3], '\0', -1, "got %#hhx expected %#hhx\n");
1277 assert_equal_return(s[4], '.', -1, "got %#hhx expected %#hhx\n");
1278
1279 tokensz = strnlen(token, max) + 1;
1280 s += tokensz;
1281 max -= tokensz;
1282 assert_equal_return(max, 5, -1, "got %d expected %d\n");
1283
1284 /*
1285 * s=".,gh," -> "\0,gh,"
1286 * ^ token
1287 */
1288 ret = strntoken(s, max, ",.", &token, &state);
1289 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1290 assert_equal_return(token, s, -1, "got %p expected %p\n");
1291 assert_equal_return(s[0], '\0', -1, "got %#hhx expected %#hhx\n");
1292 assert_equal_return(s[1], ',', -1, "got %#hhx expected %#hhx\n");
1293
1294 tokensz = strnlen(token, max) + 1;
1295 s += tokensz;
1296 max -= tokensz;
1297 assert_equal_return(max, 4, -1, "got %d expected %d\n");
1298
1299 /*
1300 * s=",gh," -> "\0gh,"
1301 * ^ token
1302 */
1303 ret = strntoken(s, max, ",.", &token, &state);
1304 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1305 assert_equal_return(token, s, -1, "got %p expected %p\n");
1306 assert_equal_return(s[0], '\0', -1, "got %#hhx expected %#hhx\n");
1307 assert_equal_return(s[1], 'g', -1, "got %#hhx expected %#hhx\n");
1308
1309 tokensz = strnlen(token, max) + 1;
1310 s += tokensz;
1311 max -= tokensz;
1312 assert_equal_return(max, 3, -1, "got %d expected %d\n");
1313
1314 /*
1315 * s="gh," -> "gh\0"
1316 * ^ token
1317 */
1318 ret = strntoken(s, max, ",.", &token, &state);
1319 assert_equal_return(ret, true, -1, "got %d expected %d\n");
1320 assert_equal_return(token, s, -1, "got %p expected %p\n");
1321 assert_equal_return(s[0], 'g', -1, "got %#hhx expected %#hhx\n");
1322 assert_equal_return(s[1], 'h', -1, "got %#hhx expected %#hhx\n");
1323 assert_equal_return(s[2], '\0', -1, "got %#hhx expected %#hhx\n");
1324
1325 tokensz = strnlen(token, max) + 1;
1326 s += tokensz;
1327 max -= tokensz;
1328 assert_equal_return(max, 0, -1, "got %d expected %d\n");
1329
1330 char *prevtok = token;
1331
1332 /*
1333 * s="" -> ""
1334 * ^ token, but max is 0
1335 */
1336 ret = strntoken(s, max, ",.", &token, &state);
1337 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1338 assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
1339 assert_equal_return(s[0], '\0', -1, "got %#hhx expected %#hhx\n");
1340
1341 s[0] = 'x';
1342 ret = strntoken(s, max, ",.", &token, &state);
1343 assert_equal_return(ret, false, -1, "got %d expected %d\n");
1344 assert_equal_return(token, prevtok, -1, "got %p expected %p\n");
1345 assert_equal_return(s[0], 'x', -1, "got %#hhx expected %#hhx\n");
1346
1347 return 0;
1348}
1349
1350static int
1351test_strntoken_with_ascii_nul(void)
1352{
1353 const char s1[] = "abc,def,.,gh,";
1354 char s2[] = "abc,def,.,gh,";
1355 char *token = NULL;
1356 bool ret;
1357 size_t max;
1358 char *s = s2;
1359 size_t tokensz;
1360 char s3[] = "abc,def,.,gh,";
1361 char state;
1362
1363 s = s2;
1364 max = sizeof(s2);
1365 assert_equal_return(max, 14, 1, "got %d expected %d\n");
1366 /*
1367 * s="abc,def,.,gh," -> "abc\0def,.,gh,"
1368 * ^ token
1369 */
1370 ret = strntoken(s, max, ",.", &token, &state);
1371 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1372 assert_equal_return(s[2], 'c', 1, "got %#hhx expected %#hhx\n");
1373 assert_equal_return(s[3], '\0', 1, "got %#hhx expected %#hhx\n");
1374 assert_equal_return(s[4], 'd', 1, "got %#hhx expected %#hhx\n");
1375
1376 tokensz = strnlen(token, max) + 1;
1377 s += tokensz;
1378 max -= tokensz;
1379 assert_equal_return(max, 10, 1, "got %d expected %d\n");
1380
1381 /*
1382 * s="def,.,gh," -> "def\0.,gh,"
1383 * ^ token
1384 */
1385 ret = strntoken(s, max, ",.", &token, &state);
1386 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1387 assert_equal_return(token, s, 1, "got %p expected %p\n");
1388 assert_equal_return(s[2], 'f', 1, "got %#hhx expected %#hhx\n");
1389 assert_equal_return(s[3], '\0', 1, "got %#hhx expected %#hhx\n");
1390 assert_equal_return(s[4], '.', 1, "got %#hhx expected %#hhx\n");
1391
1392 tokensz = strnlen(token, max) + 1;
1393 s += tokensz;
1394 max -= tokensz;
1395 assert_equal_return(max, 6, 1, "got %d expected %d\n");
1396
1397 /*
1398 * s=".,gh," -> "\0,gh,"
1399 * ^ token
1400 */
1401 ret = strntoken(s, max, ",.", &token, &state);
1402 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1403 assert_equal_return(token, s, 1, "got %p expected %p\n");
1404 assert_equal_return(s[0], '\0', 1, "got %#hhx expected %#hhx\n");
1405 assert_equal_return(s[1], ',', 1, "got %#hhx expected %#hhx\n");
1406
1407 tokensz = strnlen(token, max) + 1;
1408 s += tokensz;
1409 max -= tokensz;
1410 assert_equal_return(max, 5, 1, "got %d expected %d\n");
1411
1412 /*
1413 * s=",gh," -> "\0gh,"
1414 * ^ token
1415 */
1416 ret = strntoken(s, max, ",.", &token, &state);
1417 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1418 assert_equal_return(token, s, 1, "got %p expected %p\n");
1419 assert_equal_return(s[0], '\0', 1, "got %#hhx expected %#hhx\n");
1420 assert_equal_return(s[1], 'g', 1, "got %#hhx expected %#hhx\n");
1421
1422 tokensz = strnlen(token, max) + 1;
1423 s += tokensz;
1424 max -= tokensz;
1425 assert_equal_return(max, 4, 1, "got %d expected %d\n");
1426
1427 /*
1428 * s="gh," -> "gh\0"
1429 * ^ token
1430 */
1431 ret = strntoken(s, max, ",.", &token, &state);
1432 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1433 assert_equal_return(token, s, 1, "got %p expected %p\n");
1434 assert_equal_return(s[0], 'g', 1, "got %#hhx expected %#hhx\n");
1435 assert_equal_return(s[1], 'h', 1, "got %#hhx expected %#hhx\n");
1436 assert_equal_return(s[2], '\0', 1, "got %#hhx expected %#hhx\n");
1437
1438 tokensz = strnlen(token, max) + 1;
1439 s += tokensz;
1440 max -= tokensz;
1441 assert_equal_return(max, 1, 1, "got %d expected %d\n");
1442
1443 /*
1444 * s="" -> ""
1445 * ^ token, max is 1
1446 */
1447 ret = strntoken(s, max, ",.", &token, &state);
1448 assert_equal_return(ret, true, 1, "got %d expected %d\n");
1449 assert_equal_return(token, s, 1, "got %p expected %p\n");
1450 assert_equal_return(s[0], '\0', 1, "got %#hhx expected %#hhx\n");
1451
1452 char *prevtok = token;
1453 tokensz = strnlen(token, max) + 1;
1454 s += tokensz;
1455 max -= tokensz;
1456 assert_equal_return(max, 0, 1, "got %d expected %d\n");
1457
1458 /*
1459 * s="" -> ""
1460 * ^ token, max is 0
1461 */
1462 ret = strntoken(s, max, ",.", &token, &state);
1463 assert_equal_return(ret, false, 1, "got %d expected %d\n");
1464 assert_equal_return(token, prevtok, 1, "got %p expected %p\n");
1465
1466 return 0;
1467}
1468
1469int
1470main(void)
1471{
1472 int status = 0;
1473 test(test_strlen);
1474 test(test_strnlen);
1475 test(test_strcmp);
1476 test(test_strncmp);
1477 test(test_strcasecmp);
1478 test(test_strncasecmp);
1479 test(test_strrchr);
1480 test(test_strcpy);
1481 test(test_strncpy);
1482 test(test_strcat);
1483 test(test_stpcpy);
1484 test(test_strdup);
1485 test(test_strndup);
1486 test(test_strchr);
1487 test(test_strchrnul);
1488 test(test_strntoken_null);
1489 test(test_strntoken_size_0);
1490 test(test_strntoken_empty_size_1);
1491 test(test_strntoken_size_1);
1492 test(test_strntoken_size_2);
1493 test(test_strntoken_no_ascii_nul);
1494 test(test_strntoken_with_ascii_nul);
1495 return status;
1496}
1497
1498// vim:fenc=utf-8:tw=75:noet