1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2022 Oxide Computer Company
14 */
15
16 /*
17 * This is a regression test for illumos#14933 where asprintf() in small buffers
18 * was thrown off by an embedded NUL. Test both short and large buffers with
19 * embedded NULs. "large" at the time 14933 was anything that exceeded 128
20 * bytes.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdbool.h>
27 #include <sys/sysmacros.h>
28
29 const char *longstr = "0123456789abcdefghijklmnopqrstuvwxyz";
30
31 int
main(void)32 main(void)
33 {
34 int eval = EXIT_SUCCESS;
35 char short_exp[] = { '0', '1', '2', '3', '\0', 'a', 'b', 'c', '\0' };
36 size_t short_len = ARRAY_SIZE(short_exp);
37 size_t long_len;
38 char *out;
39 int ret;
40
41 ret = asprintf(&out, "%s%c%s", "0123", '\0', "abc");
42 if (ret != short_len - 1) {
43 (void) fprintf(stderr, "TEST FAILED: short asprintf returned "
44 "wrong length: found %u, expected %u\n", ret,
45 short_len - 1);
46 eval = EXIT_FAILURE;
47 } else {
48 (void) printf("TEST PASSED: short buffer embedded nul has "
49 "correct length\n");
50 }
51
52 if (memcmp(short_exp, out, short_len) != 0) {
53 (void) fprintf(stderr, "TEST FAILED: short example returned "
54 "wrong value\nexpected:");
55 for (size_t i = 0; i < short_len; i++) {
56 (void) fprintf(stderr, " 0x%02x", short_exp[i]);
57 }
58 (void) fprintf(stderr, "\nactual: ");
59 for (size_t i = 0; i < short_len; i++) {
60 (void) fprintf(stderr, " 0x%02x", out[i]);
61 }
62 (void) fputc('\n', stderr);
63 eval = EXIT_FAILURE;
64 } else {
65 (void) printf("TEST PASSED: short buffer data contents "
66 "match\n");
67 }
68
69 free(out);
70 long_len = strlen(longstr) * 5 + 5;
71 ret = asprintf(&out, "%s%c%s%c%s%c%s%c%s", longstr, '\0', longstr, '\0',
72 longstr, '\0', longstr, '\0', longstr);
73 if (ret != long_len - 1) {
74 (void) fprintf(stderr, "TEST FAILED: long asprintf returned "
75 "wrong length: found %u, expected %u\n", ret, long_len - 1);
76 eval = EXIT_FAILURE;
77 } else {
78 (void) printf("TEST PASSED: long buffer embedded nul has "
79 "correct length\n");
80 }
81
82 bool large_pass = true;
83 for (uint_t i = 0; i < 5; i++) {
84 size_t offset = (strlen(longstr) + 1) * i;
85 if (strcmp(longstr, out + offset) != 0) {
86 (void) fprintf(stderr, "TEST FAILED: long asprintf "
87 "data buffer mismatch at copy %u\n", i);
88 eval = EXIT_FAILURE;
89 large_pass = false;
90 }
91 }
92 if (large_pass) {
93 (void) printf("TEST PASSED: long buffer data contents match\n");
94 }
95
96 return (eval);
97 }
98