xref: /illumos-gate/usr/src/test/libc-tests/tests/asprintf-14933.c (revision fc910014e8a32a65612105835a10995f2c13d942)
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
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