xref: /illumos-gate/usr/src/test/libc-tests/tests/swprintf-17781.c (revision ac2250cb76bb32944fd2c8a3ba2cd3f79747748d)
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 2026 Hans Rosenfeld
14  */
15 
16 /*
17  * Regression test for illumos #17781. The refactoring of the various *printf
18  * functions in #17182 missed a corner case of [v]swprintf(), which need to go
19  * through a special code path in _ndoprnt() using wmemcpy() for output into
20  * string rather than wctomb(). This is indicated by the _IOREAD flag on the
21  * temporary FILE created by vswprintf() for the output string, but the check
22  * in _ndoprnt() erroneously insisted that this is the only flag set.
23  *
24  * As a result, [v]swprintf() write multibyte characters according to the
25  * LC_CTYPE of the current locale, instead of wchar_t as they ought to.
26  */
27 
28 #include <sys/sysmacros.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <wchar.h>
32 
33 wchar_t foo[] = L"bl0rg";
34 wchar_t bar[6];
35 
36 void
37 hexdump(char *buf, int len)
38 {
39 	int i;
40 
41 	for (i = 0; i != len; i++)
42 		fprintf(stderr, "%02x ", buf[i]);
43 }
44 
45 int
46 main(int argc, char **argv)
47 {
48 	int len;
49 
50 	len = swprintf(bar, ARRAY_SIZE(bar), L"%ls", foo);
51 
52 	if (len != ARRAY_SIZE(foo) - 1) {
53 		fprintf(stderr, "length mismatch: expected %d != actual %d",
54 		    ARRAY_SIZE(foo) - 1, len);
55 		return (1);
56 	}
57 
58 	if (memcmp(foo, bar, sizeof (foo)) != 0) {
59 		fprintf(stderr, "output mismatch:\n");
60 		fprintf(stderr, "expected: ");
61 		hexdump((char *)foo, sizeof (foo));
62 		fprintf(stderr, "\n");
63 		fprintf(stderr, "actual:   ");
64 		hexdump((char *)bar, sizeof (bar));
65 		fprintf(stderr, "\n");
66 
67 		return (1);
68 	}
69 
70 	return (0);
71 }
72