1314817Sngie/* $NetBSD: t_strlen.c,v 1.6 2017/01/14 20:49:24 christos Exp $ */
2272343Sngie
3272343Sngie/*
4272343Sngie * Written by J.T. Conklin <jtc@acorntoolworks.com>
5272343Sngie * Public domain.
6272343Sngie */
7272343Sngie
8272343Sngie#include <atf-c.h>
9272343Sngie#include <string.h>
10272343Sngie#include <unistd.h>
11272343Sngie#include <stdio.h>
12272343Sngie#include <stdlib.h>
13272343Sngie#include <dlfcn.h>
14272343Sngie#include <unistd.h>
15272343Sngie
16272343Sngiestatic void	write_num(int);
17272343Sngie
18272343Sngiestatic void
19272343Sngiewrite_num(int val)
20272343Sngie{
21272343Sngie	char buf[20];
22272343Sngie	int i;
23272343Sngie
24272343Sngie	for (i = sizeof buf; --i >= 0;) {
25272343Sngie		buf[i] = '0' + val % 10;
26272343Sngie		val /= 10;
27272343Sngie		if (val == 0) {
28272343Sngie			write(2, buf + i, sizeof buf - i);
29272343Sngie			return;
30272343Sngie		}
31272343Sngie	}
32272343Sngie	write(2, "overflow", 8);
33272343Sngie}
34272343Sngie
35272343SngieATF_TC(strlen_basic);
36272343SngieATF_TC_HEAD(strlen_basic, tc)
37272343Sngie{
38272343Sngie        atf_tc_set_md_var(tc, "descr", "Test strlen(3) results");
39272343Sngie}
40272343Sngie
41272343SngieATF_TC_BODY(strlen_basic, tc)
42272343Sngie{
43311611Sngie	void *dl_handle;
44272343Sngie	/* try to trick the compiler */
45272343Sngie	size_t (*strlen_fn)(const char *);
46272343Sngie
47272343Sngie	unsigned int a, t;
48272343Sngie	size_t len;
49272343Sngie	char buf[64];
50272343Sngie
51272343Sngie	struct tab {
52272343Sngie		const char*	val;
53272343Sngie		size_t		len;
54272343Sngie	};
55272343Sngie
56272343Sngie	const struct tab tab[] = {
57272343Sngie		/*
58272343Sngie		 * patterns that check for all combinations of leading and
59272343Sngie		 * trailing unaligned characters (on a 64 bit processor)
60272343Sngie		 */
61272343Sngie
62272343Sngie		{ "",				0 },
63272343Sngie		{ "a",				1 },
64272343Sngie		{ "ab",				2 },
65272343Sngie		{ "abc",			3 },
66272343Sngie		{ "abcd",			4 },
67272343Sngie		{ "abcde",			5 },
68272343Sngie		{ "abcdef",			6 },
69272343Sngie		{ "abcdefg",			7 },
70272343Sngie		{ "abcdefgh",			8 },
71272343Sngie		{ "abcdefghi",			9 },
72272343Sngie		{ "abcdefghij",			10 },
73272343Sngie		{ "abcdefghijk",		11 },
74272343Sngie		{ "abcdefghijkl",		12 },
75272343Sngie		{ "abcdefghijklm",		13 },
76272343Sngie		{ "abcdefghijklmn",		14 },
77272343Sngie		{ "abcdefghijklmno",		15 },
78272343Sngie		{ "abcdefghijklmnop",		16 },
79272343Sngie		{ "abcdefghijklmnopq",		17 },
80272343Sngie		{ "abcdefghijklmnopqr",		18 },
81272343Sngie		{ "abcdefghijklmnopqrs",	19 },
82272343Sngie		{ "abcdefghijklmnopqrst",	20 },
83272343Sngie		{ "abcdefghijklmnopqrstu",	21 },
84272343Sngie		{ "abcdefghijklmnopqrstuv",	22 },
85272343Sngie		{ "abcdefghijklmnopqrstuvw",	23 },
86272343Sngie
87272343Sngie		/*
88272343Sngie		 * patterns that check for the cases where the expression:
89272343Sngie		 *
90272343Sngie		 *	((word - 0x7f7f..7f) & 0x8080..80)
91272343Sngie		 *
92272343Sngie		 * returns non-zero even though there are no zero bytes in
93272343Sngie		 * the word.
94272343Sngie		 */
95272343Sngie
96272343Sngie		{ "" "\xff\xff\xff\xff\xff\xff\xff\xff" "abcdefgh",	16 },
97272343Sngie		{ "a" "\xff\xff\xff\xff\xff\xff\xff\xff" "bcdefgh",	16 },
98272343Sngie		{ "ab" "\xff\xff\xff\xff\xff\xff\xff\xff" "cdefgh",	16 },
99272343Sngie		{ "abc" "\xff\xff\xff\xff\xff\xff\xff\xff" "defgh",	16 },
100272343Sngie		{ "abcd" "\xff\xff\xff\xff\xff\xff\xff\xff" "efgh",	16 },
101272343Sngie		{ "abcde" "\xff\xff\xff\xff\xff\xff\xff\xff" "fgh",	16 },
102272343Sngie		{ "abcdef" "\xff\xff\xff\xff\xff\xff\xff\xff" "gh",	16 },
103272343Sngie		{ "abcdefg" "\xff\xff\xff\xff\xff\xff\xff\xff" "h",	16 },
104272343Sngie		{ "abcdefgh" "\xff\xff\xff\xff\xff\xff\xff\xff" "",	16 },
105272343Sngie	};
106272343Sngie
107272343Sngie	/*
108272343Sngie	 * During testing it is useful have the rest of the program
109272343Sngie	 * use a known good version!
110272343Sngie	 */
111311611Sngie	dl_handle = dlopen(NULL, RTLD_LAZY);
112311611Sngie	strlen_fn = dlsym(dl_handle, "test_strlen");
113272343Sngie	if (!strlen_fn)
114272343Sngie		strlen_fn = strlen;
115272343Sngie
116272343Sngie	for (a = 0; a < sizeof(long); ++a) {
117272343Sngie		for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) {
118272343Sngie
119272343Sngie			memcpy(&buf[a], tab[t].val, tab[t].len + 1);
120272343Sngie			len = strlen_fn(&buf[a]);
121272343Sngie
122272343Sngie			if (len != tab[t].len) {
123272343Sngie				/* Write error without using printf / strlen */
124272343Sngie				write(2, "alignment ", 10);
125272343Sngie				write_num(a);
126272343Sngie				write(2, ", test ", 7);
127272343Sngie				write_num(t);
128272343Sngie				write(2, ", got len ", 10);
129272343Sngie				write_num(len);
130272343Sngie				write(2, ", not ", 6);
131272343Sngie				write_num(tab[t].len);
132272343Sngie				write(2, ", for '", 7);
133272343Sngie				write(2, tab[t].val, tab[t].len);
134272343Sngie				write(2, "'\n", 2);
135272343Sngie				atf_tc_fail("See stderr for details");
136272343Sngie			}
137272343Sngie		}
138272343Sngie	}
139311611Sngie	(void)dlclose(dl_handle);
140272343Sngie}
141272343Sngie
142272343SngieATF_TC(strlen_huge);
143272343SngieATF_TC_HEAD(strlen_huge, tc)
144272343Sngie{
145272343Sngie        atf_tc_set_md_var(tc, "descr", "Test strlen(3) with huge strings");
146272343Sngie}
147272343Sngie
148272343SngieATF_TC_BODY(strlen_huge, tc)
149272343Sngie{
150272343Sngie	long page;
151272343Sngie	char *str;
152272343Sngie	size_t i;
153272343Sngie
154272343Sngie	page = sysconf(_SC_PAGESIZE);
155272343Sngie	ATF_REQUIRE(page >= 0);
156272343Sngie
157272343Sngie	for (i = 1; i < 1000; i = i + 100) {
158272343Sngie
159272343Sngie		str = malloc(i * page + 1);
160272343Sngie
161272343Sngie		if (str == NULL)
162272343Sngie			continue;
163272343Sngie
164272343Sngie		(void)memset(str, 'x', i * page);
165272343Sngie		str[i * page] = '\0';
166272343Sngie
167272343Sngie		ATF_REQUIRE(strlen(str) == i * page);
168272343Sngie		free(str);
169272343Sngie	}
170272343Sngie}
171272343Sngie
172272343SngieATF_TC(strnlen_basic);
173272343SngieATF_TC_HEAD(strnlen_basic, tc)
174272343Sngie{
175272343Sngie        atf_tc_set_md_var(tc, "descr", "A naive test of strnlen(3)");
176272343Sngie}
177272343Sngie
178272343SngieATF_TC_BODY(strnlen_basic, tc)
179272343Sngie{
180272343Sngie	char buf[1];
181272343Sngie
182272343Sngie	buf[0] = '\0';
183272343Sngie
184272343Sngie	ATF_CHECK(strnlen(buf, 000) == 0);
185272343Sngie	ATF_CHECK(strnlen(buf, 111) == 0);
186272343Sngie
187272343Sngie	ATF_CHECK(strnlen("xxx", 0) == 0);
188272343Sngie	ATF_CHECK(strnlen("xxx", 1) == 1);
189272343Sngie	ATF_CHECK(strnlen("xxx", 2) == 2);
190272343Sngie	ATF_CHECK(strnlen("xxx", 3) == 3);
191272343Sngie	ATF_CHECK(strnlen("xxx", 9) == 3);
192272343Sngie}
193272343Sngie
194272343SngieATF_TP_ADD_TCS(tp)
195272343Sngie{
196272343Sngie
197272343Sngie	ATF_TP_ADD_TC(tp, strlen_basic);
198272343Sngie	ATF_TP_ADD_TC(tp, strlen_huge);
199272343Sngie	ATF_TP_ADD_TC(tp, strnlen_basic);
200272343Sngie
201272343Sngie	return atf_no_error();
202272343Sngie}
203