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