xref: /freebsd/contrib/netbsd-tests/lib/libc/gen/t_vis.c (revision 79e6ffb6951bd75a92326fabadd48e87ee0aed96)
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);
ATF_TC_HEAD(strvis_basic,tc)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 
ATF_TC_BODY(strvis_basic,tc)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);
ATF_TC_HEAD(strvis_null,tc)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 
ATF_TC_BODY(strvis_null,tc)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);
ATF_TC_HEAD(strvis_empty,tc)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 
ATF_TC_BODY(strvis_empty,tc)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);
ATF_TC_HEAD(strunvis_hex,tc)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 
ATF_TC_BODY(strunvis_hex,tc)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);
ATF_TC_HEAD(strvis_locale,tc)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 
ATF_TC_BODY(strvis_locale,tc)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 
1782f489a50SKyle Evans #ifdef __FreeBSD__
179*79e6ffb6SKyle Evans #define	STRVIS_OVERFLOW_MARKER	((char)0xff)	/* Arbitrary */
1802f489a50SKyle Evans 
1812f489a50SKyle Evans ATF_TC(strvis_overflow_mb);
ATF_TC_HEAD(strvis_overflow_mb,tc)1822f489a50SKyle Evans ATF_TC_HEAD(strvis_overflow_mb, tc)
1832f489a50SKyle Evans {
1842f489a50SKyle Evans 	atf_tc_set_md_var(tc, "descr", "Test strvis(3) multi-byte overflow");
1852f489a50SKyle Evans }
1862f489a50SKyle Evans 
ATF_TC_BODY(strvis_overflow_mb,tc)1872f489a50SKyle Evans ATF_TC_BODY(strvis_overflow_mb, tc)
1882f489a50SKyle Evans {
1892f489a50SKyle Evans 	const char src[] = "\xf0\x9f\xa5\x91";
1902f489a50SKyle Evans 	/* Extra byte to detect overflow */
1912f489a50SKyle Evans 	char dst[sizeof(src) + 1];
1922f489a50SKyle Evans 	int n;
1932f489a50SKyle Evans 
1942f489a50SKyle Evans 	setlocale(LC_CTYPE, "en_US.UTF-8");
1952f489a50SKyle Evans 
1962f489a50SKyle Evans 	/* Arbitrary */
1972f489a50SKyle Evans 	memset(dst, STRVIS_OVERFLOW_MARKER, sizeof(dst));
1982f489a50SKyle Evans 
1992f489a50SKyle Evans 	/*
2002f489a50SKyle Evans 	 * If we only provide four bytes of buffer, we shouldn't be able encode
2012f489a50SKyle Evans 	 * a full 4-byte sequence.
2022f489a50SKyle Evans 	 */
2032f489a50SKyle Evans 	n = strnvis(dst, 4, src, VIS_SAFE);
2042f489a50SKyle Evans 	ATF_REQUIRE(dst[4] == STRVIS_OVERFLOW_MARKER);
2052f489a50SKyle Evans 	ATF_REQUIRE(n == -1);
2062f489a50SKyle Evans 
2072f489a50SKyle Evans 	n = strnvis(dst, sizeof(src), src, VIS_SAFE);
2082f489a50SKyle Evans 	ATF_REQUIRE(n == sizeof(src) - 1);
2092f489a50SKyle Evans }
2102f489a50SKyle Evans 
2112f489a50SKyle Evans ATF_TC(strvis_overflow_c);
ATF_TC_HEAD(strvis_overflow_c,tc)2122f489a50SKyle Evans ATF_TC_HEAD(strvis_overflow_c, tc)
2132f489a50SKyle Evans {
2142f489a50SKyle Evans 	atf_tc_set_md_var(tc, "descr", "Test strvis(3) C locale overflow");
2152f489a50SKyle Evans }
2162f489a50SKyle Evans 
ATF_TC_BODY(strvis_overflow_c,tc)2172f489a50SKyle Evans ATF_TC_BODY(strvis_overflow_c, tc)
2182f489a50SKyle Evans {
2192f489a50SKyle Evans 	const char src[] = "AAAA";
2202f489a50SKyle Evans 	/* Extra byte to detect overflow */
2212f489a50SKyle Evans 	char dst[sizeof(src) + 1];
2222f489a50SKyle Evans 	int n;
2232f489a50SKyle Evans 
2242f489a50SKyle Evans 	/* Arbitrary */
2252f489a50SKyle Evans 	memset(dst, STRVIS_OVERFLOW_MARKER, sizeof(dst));
2262f489a50SKyle Evans 
2272f489a50SKyle Evans 	/*
2282f489a50SKyle Evans 	 * If we only provide four bytes of buffer, we shouldn't be able encode
2292f489a50SKyle Evans 	 * 4 bytes of input.
2302f489a50SKyle Evans 	 */
2312f489a50SKyle Evans 	n = strnvis(dst, 4, src, VIS_SAFE | VIS_NOLOCALE);
2322f489a50SKyle Evans 	ATF_REQUIRE(dst[4] == STRVIS_OVERFLOW_MARKER);
2332f489a50SKyle Evans 	ATF_REQUIRE(n == -1);
2342f489a50SKyle Evans 
2352f489a50SKyle Evans 	n = strnvis(dst, sizeof(src), src, VIS_SAFE | VIS_NOLOCALE);
2362f489a50SKyle Evans 	ATF_REQUIRE(n == sizeof(src) - 1);
2372f489a50SKyle Evans }
2382f489a50SKyle Evans #endif /* __FreeBSD__ */
2392f489a50SKyle Evans 
ATF_TP_ADD_TCS(tp)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 */
2502f489a50SKyle Evans #ifdef __FreeBSD__
2512f489a50SKyle Evans 	ATF_TP_ADD_TC(tp, strvis_overflow_mb);
2522f489a50SKyle Evans 	ATF_TP_ADD_TC(tp, strvis_overflow_c);
2532f489a50SKyle Evans #endif
25457718be8SEnji Cooper 
25557718be8SEnji Cooper 	return atf_no_error();
25657718be8SEnji Cooper }
257