xref: /freebsd/contrib/netbsd-tests/lib/libc/gen/t_vis.c (revision 2f489a509e615c46be6f7c6aa7cea161f50f18af)
1ddba0402SEnji Cooper /*	$NetBSD: t_vis.c,v 1.9 2017/01/10 15:16:57 christos Exp $	*/
257718be8SEnji Cooper 
357718be8SEnji Cooper /*-
457718be8SEnji Cooper  * Copyright (c) 2002 The NetBSD Foundation, Inc.
557718be8SEnji Cooper  * All rights reserved.
657718be8SEnji Cooper  *
757718be8SEnji Cooper  * This code was contributed to The NetBSD Foundation by Christos Zoulas.
857718be8SEnji Cooper  *
957718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
1057718be8SEnji Cooper  * modification, are permitted provided that the following conditions
1157718be8SEnji Cooper  * are met:
1257718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1357718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1457718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1557718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1657718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1757718be8SEnji Cooper  *
1857718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1957718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2057718be8SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2157718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2257718be8SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2357718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2457718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2557718be8SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2657718be8SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2757718be8SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2857718be8SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
2957718be8SEnji Cooper  */
3057718be8SEnji Cooper 
3157718be8SEnji Cooper #include <atf-c.h>
3257718be8SEnji Cooper 
3357718be8SEnji Cooper #include <string.h>
3457718be8SEnji Cooper #include <stdlib.h>
35640235e2SEnji Cooper #include <locale.h>
3657718be8SEnji Cooper #include <err.h>
3757718be8SEnji Cooper #include <vis.h>
3857718be8SEnji Cooper 
3957718be8SEnji Cooper static int styles[] = {
4057718be8SEnji Cooper 	VIS_OCTAL,
4157718be8SEnji Cooper 	VIS_CSTYLE,
4257718be8SEnji Cooper 	VIS_SP,
4357718be8SEnji Cooper 	VIS_TAB,
4457718be8SEnji Cooper 	VIS_NL,
4557718be8SEnji Cooper 	VIS_WHITE,
4657718be8SEnji Cooper 	VIS_SAFE,
4757718be8SEnji Cooper #if 0	/* Not reversible */
4857718be8SEnji Cooper 	VIS_NOSLASH,
4957718be8SEnji Cooper #endif
5057718be8SEnji Cooper 	VIS_HTTP1808,
5157718be8SEnji Cooper 	VIS_MIMESTYLE,
5257718be8SEnji Cooper #if 0	/* Not supported by vis(3) */
5357718be8SEnji Cooper 	VIS_HTTP1866,
5457718be8SEnji Cooper #endif
5557718be8SEnji Cooper };
5657718be8SEnji Cooper 
5757718be8SEnji Cooper #define SIZE	256
5857718be8SEnji Cooper 
5957718be8SEnji Cooper ATF_TC(strvis_basic);
6057718be8SEnji Cooper ATF_TC_HEAD(strvis_basic, tc)
6157718be8SEnji Cooper {
6257718be8SEnji Cooper 
6357718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test strvis(3)");
6457718be8SEnji Cooper }
6557718be8SEnji Cooper 
6657718be8SEnji Cooper ATF_TC_BODY(strvis_basic, tc)
6757718be8SEnji Cooper {
6857718be8SEnji Cooper 	char *srcbuf, *dstbuf, *visbuf;
6957718be8SEnji Cooper 	unsigned int i, j;
7057718be8SEnji Cooper 
7157718be8SEnji Cooper 	ATF_REQUIRE((dstbuf = malloc(SIZE)) != NULL);
7257718be8SEnji Cooper 	ATF_REQUIRE((srcbuf = malloc(SIZE)) != NULL);
7357718be8SEnji Cooper 	ATF_REQUIRE((visbuf = malloc(SIZE * 4 + 1)) != NULL);
7457718be8SEnji Cooper 
7557718be8SEnji Cooper 	for (i = 0; i < SIZE; i++)
7657718be8SEnji Cooper 		srcbuf[i] = (char)i;
7757718be8SEnji Cooper 
7857718be8SEnji Cooper 	for (i = 0; i < __arraycount(styles); i++) {
7957718be8SEnji Cooper 		ATF_REQUIRE(strsvisx(visbuf, srcbuf, SIZE, styles[i], "") > 0);
8057718be8SEnji Cooper 		memset(dstbuf, 0, SIZE);
8157718be8SEnji Cooper 		ATF_REQUIRE(strunvisx(dstbuf, visbuf,
8257718be8SEnji Cooper 		    styles[i] & (VIS_HTTP1808|VIS_MIMESTYLE)) > 0);
8357718be8SEnji Cooper 		for (j = 0; j < SIZE; j++)
8457718be8SEnji Cooper 			if (dstbuf[j] != (char)j)
8557718be8SEnji Cooper 				atf_tc_fail_nonfatal("Failed for style %x, "
8657718be8SEnji Cooper 				    "char %d [%d]", styles[i], j, dstbuf[j]);
8757718be8SEnji Cooper 	}
8857718be8SEnji Cooper 	free(dstbuf);
8957718be8SEnji Cooper 	free(srcbuf);
9057718be8SEnji Cooper 	free(visbuf);
9157718be8SEnji Cooper }
9257718be8SEnji Cooper 
9357718be8SEnji Cooper ATF_TC(strvis_null);
9457718be8SEnji Cooper ATF_TC_HEAD(strvis_null, tc)
9557718be8SEnji Cooper {
9657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test strvis(3) NULL");
9757718be8SEnji Cooper }
9857718be8SEnji Cooper 
9957718be8SEnji Cooper ATF_TC_BODY(strvis_null, tc)
10057718be8SEnji Cooper {
10157718be8SEnji Cooper 	char dst[] = "fail";
10257718be8SEnji Cooper 	strvis(dst, NULL, VIS_SAFE);
10357718be8SEnji Cooper 	ATF_REQUIRE(dst[0] == '\0' && dst[1] == 'a');
10457718be8SEnji Cooper }
10557718be8SEnji Cooper 
10657718be8SEnji Cooper ATF_TC(strvis_empty);
10757718be8SEnji Cooper ATF_TC_HEAD(strvis_empty, tc)
10857718be8SEnji Cooper {
10957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test strvis(3) empty");
11057718be8SEnji Cooper }
11157718be8SEnji Cooper 
11257718be8SEnji Cooper ATF_TC_BODY(strvis_empty, tc)
11357718be8SEnji Cooper {
11457718be8SEnji Cooper 	char dst[] = "fail";
11557718be8SEnji Cooper 	strvis(dst, "", VIS_SAFE);
11657718be8SEnji Cooper 	ATF_REQUIRE(dst[0] == '\0' && dst[1] == 'a');
11757718be8SEnji Cooper }
11857718be8SEnji Cooper 
11957718be8SEnji Cooper ATF_TC(strunvis_hex);
12057718be8SEnji Cooper ATF_TC_HEAD(strunvis_hex, tc)
12157718be8SEnji Cooper {
12257718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test strunvis(3) \\xXX");
12357718be8SEnji Cooper }
12457718be8SEnji Cooper 
12557718be8SEnji Cooper ATF_TC_BODY(strunvis_hex, tc)
12657718be8SEnji Cooper {
12757718be8SEnji Cooper 	static const struct {
12857718be8SEnji Cooper 		const char *e;
12957718be8SEnji Cooper 		const char *d;
13057718be8SEnji Cooper 		int error;
13157718be8SEnji Cooper 	} ed[] = {
13257718be8SEnji Cooper 		{ "\\xff", "\xff", 1 },
13357718be8SEnji Cooper 		{ "\\x1", "\x1", 1 },
13457718be8SEnji Cooper 		{ "\\x1\\x02", "\x1\x2", 2 },
13557718be8SEnji Cooper 		{ "\\x1x", "\x1x", 2 },
13657718be8SEnji Cooper 		{ "\\xx", "", -1 },
13757718be8SEnji Cooper 	};
13857718be8SEnji Cooper 	char uv[10];
13957718be8SEnji Cooper 
14057718be8SEnji Cooper 	for (size_t i = 0; i < __arraycount(ed); i++) {
14157718be8SEnji Cooper 		ATF_REQUIRE(strunvis(uv, ed[i].e) == ed[i].error);
14257718be8SEnji Cooper 		if (ed[i].error > 0)
14357718be8SEnji Cooper 			ATF_REQUIRE(memcmp(ed[i].d, uv, ed[i].error) == 0);
14457718be8SEnji Cooper 	}
14557718be8SEnji Cooper }
14657718be8SEnji Cooper 
14772a02000SEnji Cooper #ifdef VIS_NOLOCALE
148640235e2SEnji Cooper ATF_TC(strvis_locale);
149640235e2SEnji Cooper ATF_TC_HEAD(strvis_locale, tc)
150640235e2SEnji Cooper {
151640235e2SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test strvis(3) with locale");
152640235e2SEnji Cooper }
153640235e2SEnji Cooper 
154640235e2SEnji Cooper ATF_TC_BODY(strvis_locale, tc)
155640235e2SEnji Cooper {
156640235e2SEnji Cooper 	char s[256], cd[sizeof(s) * 4 + 1], jd[sizeof(cd)], *ol;
157640235e2SEnji Cooper 	int jr, cr;
158640235e2SEnji Cooper 
159640235e2SEnji Cooper 	for (size_t i = 0; i < sizeof(s) - 1; i++)
160640235e2SEnji Cooper 		s[i] = i + 1;
161640235e2SEnji Cooper 	s[sizeof(s) - 1] = '\0';
162640235e2SEnji Cooper 
163640235e2SEnji Cooper 	ol = setlocale(LC_CTYPE, "ja_JP.UTF-8");
164640235e2SEnji Cooper 	ATF_REQUIRE(ol != NULL);
165640235e2SEnji Cooper 	jr = strvisx(jd, s, sizeof(s), VIS_WHITE | VIS_NOLOCALE);
166640235e2SEnji Cooper 	ATF_REQUIRE(jr != -1);
167640235e2SEnji Cooper 	ol = strdup(ol);
168640235e2SEnji Cooper 	ATF_REQUIRE(ol != NULL);
169640235e2SEnji Cooper 	ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL);
170640235e2SEnji Cooper 	cr = strvisx(cd, s, sizeof(s), VIS_WHITE);
171640235e2SEnji Cooper 	ATF_REQUIRE(jr == cr);
172640235e2SEnji Cooper 	ATF_REQUIRE(memcmp(jd, cd, jr) == 0);
173640235e2SEnji Cooper 	setlocale(LC_CTYPE, ol);
174640235e2SEnji Cooper 	free(ol);
175640235e2SEnji Cooper }
17672a02000SEnji Cooper #endif /* VIS_NOLOCALE */
177640235e2SEnji Cooper 
178*2f489a50SKyle Evans #ifdef __FreeBSD__
179*2f489a50SKyle Evans #define	STRVIS_OVERFLOW_MARKER	0xff	/* Arbitrary */
180*2f489a50SKyle Evans 
181*2f489a50SKyle Evans ATF_TC(strvis_overflow_mb);
182*2f489a50SKyle Evans ATF_TC_HEAD(strvis_overflow_mb, tc)
183*2f489a50SKyle Evans {
184*2f489a50SKyle Evans 	atf_tc_set_md_var(tc, "descr", "Test strvis(3) multi-byte overflow");
185*2f489a50SKyle Evans }
186*2f489a50SKyle Evans 
187*2f489a50SKyle Evans ATF_TC_BODY(strvis_overflow_mb, tc)
188*2f489a50SKyle Evans {
189*2f489a50SKyle Evans 	const char src[] = "\xf0\x9f\xa5\x91";
190*2f489a50SKyle Evans 	/* Extra byte to detect overflow */
191*2f489a50SKyle Evans 	char dst[sizeof(src) + 1];
192*2f489a50SKyle Evans 	int n;
193*2f489a50SKyle Evans 
194*2f489a50SKyle Evans 	setlocale(LC_CTYPE, "en_US.UTF-8");
195*2f489a50SKyle Evans 
196*2f489a50SKyle Evans 	/* Arbitrary */
197*2f489a50SKyle Evans 	memset(dst, STRVIS_OVERFLOW_MARKER, sizeof(dst));
198*2f489a50SKyle Evans 
199*2f489a50SKyle Evans 	/*
200*2f489a50SKyle Evans 	 * If we only provide four bytes of buffer, we shouldn't be able encode
201*2f489a50SKyle Evans 	 * a full 4-byte sequence.
202*2f489a50SKyle Evans 	 */
203*2f489a50SKyle Evans 	n = strnvis(dst, 4, src, VIS_SAFE);
204*2f489a50SKyle Evans 	ATF_REQUIRE(dst[4] == STRVIS_OVERFLOW_MARKER);
205*2f489a50SKyle Evans 	ATF_REQUIRE(n == -1);
206*2f489a50SKyle Evans 
207*2f489a50SKyle Evans 	n = strnvis(dst, sizeof(src), src, VIS_SAFE);
208*2f489a50SKyle Evans 	ATF_REQUIRE(n == sizeof(src) - 1);
209*2f489a50SKyle Evans }
210*2f489a50SKyle Evans 
211*2f489a50SKyle Evans ATF_TC(strvis_overflow_c);
212*2f489a50SKyle Evans ATF_TC_HEAD(strvis_overflow_c, tc)
213*2f489a50SKyle Evans {
214*2f489a50SKyle Evans 	atf_tc_set_md_var(tc, "descr", "Test strvis(3) C locale overflow");
215*2f489a50SKyle Evans }
216*2f489a50SKyle Evans 
217*2f489a50SKyle Evans ATF_TC_BODY(strvis_overflow_c, tc)
218*2f489a50SKyle Evans {
219*2f489a50SKyle Evans 	const char src[] = "AAAA";
220*2f489a50SKyle Evans 	/* Extra byte to detect overflow */
221*2f489a50SKyle Evans 	char dst[sizeof(src) + 1];
222*2f489a50SKyle Evans 	int n;
223*2f489a50SKyle Evans 
224*2f489a50SKyle Evans 	/* Arbitrary */
225*2f489a50SKyle Evans 	memset(dst, STRVIS_OVERFLOW_MARKER, sizeof(dst));
226*2f489a50SKyle Evans 
227*2f489a50SKyle Evans 	/*
228*2f489a50SKyle Evans 	 * If we only provide four bytes of buffer, we shouldn't be able encode
229*2f489a50SKyle Evans 	 * 4 bytes of input.
230*2f489a50SKyle Evans 	 */
231*2f489a50SKyle Evans 	n = strnvis(dst, 4, src, VIS_SAFE | VIS_NOLOCALE);
232*2f489a50SKyle Evans 	ATF_REQUIRE(dst[4] == STRVIS_OVERFLOW_MARKER);
233*2f489a50SKyle Evans 	ATF_REQUIRE(n == -1);
234*2f489a50SKyle Evans 
235*2f489a50SKyle Evans 	n = strnvis(dst, sizeof(src), src, VIS_SAFE | VIS_NOLOCALE);
236*2f489a50SKyle Evans 	ATF_REQUIRE(n == sizeof(src) - 1);
237*2f489a50SKyle Evans }
238*2f489a50SKyle Evans #endif /* __FreeBSD__ */
239*2f489a50SKyle Evans 
24057718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
24157718be8SEnji Cooper {
24257718be8SEnji Cooper 
24357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, strvis_basic);
24457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, strvis_null);
24557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, strvis_empty);
24657718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, strunvis_hex);
24772a02000SEnji Cooper #ifdef VIS_NOLOCALE
248640235e2SEnji Cooper 	ATF_TP_ADD_TC(tp, strvis_locale);
24972a02000SEnji Cooper #endif /* VIS_NOLOCALE */
250*2f489a50SKyle Evans #ifdef __FreeBSD__
251*2f489a50SKyle Evans 	ATF_TP_ADD_TC(tp, strvis_overflow_mb);
252*2f489a50SKyle Evans 	ATF_TP_ADD_TC(tp, strvis_overflow_c);
253*2f489a50SKyle Evans #endif
25457718be8SEnji Cooper 
25557718be8SEnji Cooper 	return atf_no_error();
25657718be8SEnji Cooper }
257