t_strlen.c revision 311611
1/* $NetBSD: t_strlen.c,v 1.5 2011/07/14 07:33:20 jruoho Exp $ */
2
3/*
4 * Written by J.T. Conklin <jtc@acorntoolworks.com>
5 * Public domain.
6 */
7
8#include <atf-c.h>
9#include <string.h>
10#include <unistd.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <dlfcn.h>
14#include <unistd.h>
15
16static void	write_num(int);
17
18static void
19write_num(int val)
20{
21	char buf[20];
22	int i;
23
24	for (i = sizeof buf; --i >= 0;) {
25		buf[i] = '0' + val % 10;
26		val /= 10;
27		if (val == 0) {
28			write(2, buf + i, sizeof buf - i);
29			return;
30		}
31	}
32	write(2, "overflow", 8);
33}
34
35ATF_TC(strlen_basic);
36ATF_TC_HEAD(strlen_basic, tc)
37{
38        atf_tc_set_md_var(tc, "descr", "Test strlen(3) results");
39}
40
41ATF_TC_BODY(strlen_basic, tc)
42{
43#ifdef	__FreeBSD__
44	void *dl_handle;
45#endif
46	/* try to trick the compiler */
47	size_t (*strlen_fn)(const char *);
48
49	unsigned int a, t;
50	size_t len;
51	char buf[64];
52
53	struct tab {
54		const char*	val;
55		size_t		len;
56	};
57
58	const struct tab tab[] = {
59		/*
60		 * patterns that check for all combinations of leading and
61		 * trailing unaligned characters (on a 64 bit processor)
62		 */
63
64		{ "",				0 },
65		{ "a",				1 },
66		{ "ab",				2 },
67		{ "abc",			3 },
68		{ "abcd",			4 },
69		{ "abcde",			5 },
70		{ "abcdef",			6 },
71		{ "abcdefg",			7 },
72		{ "abcdefgh",			8 },
73		{ "abcdefghi",			9 },
74		{ "abcdefghij",			10 },
75		{ "abcdefghijk",		11 },
76		{ "abcdefghijkl",		12 },
77		{ "abcdefghijklm",		13 },
78		{ "abcdefghijklmn",		14 },
79		{ "abcdefghijklmno",		15 },
80		{ "abcdefghijklmnop",		16 },
81		{ "abcdefghijklmnopq",		17 },
82		{ "abcdefghijklmnopqr",		18 },
83		{ "abcdefghijklmnopqrs",	19 },
84		{ "abcdefghijklmnopqrst",	20 },
85		{ "abcdefghijklmnopqrstu",	21 },
86		{ "abcdefghijklmnopqrstuv",	22 },
87		{ "abcdefghijklmnopqrstuvw",	23 },
88
89		/*
90		 * patterns that check for the cases where the expression:
91		 *
92		 *	((word - 0x7f7f..7f) & 0x8080..80)
93		 *
94		 * returns non-zero even though there are no zero bytes in
95		 * the word.
96		 */
97
98		{ "" "\xff\xff\xff\xff\xff\xff\xff\xff" "abcdefgh",	16 },
99		{ "a" "\xff\xff\xff\xff\xff\xff\xff\xff" "bcdefgh",	16 },
100		{ "ab" "\xff\xff\xff\xff\xff\xff\xff\xff" "cdefgh",	16 },
101		{ "abc" "\xff\xff\xff\xff\xff\xff\xff\xff" "defgh",	16 },
102		{ "abcd" "\xff\xff\xff\xff\xff\xff\xff\xff" "efgh",	16 },
103		{ "abcde" "\xff\xff\xff\xff\xff\xff\xff\xff" "fgh",	16 },
104		{ "abcdef" "\xff\xff\xff\xff\xff\xff\xff\xff" "gh",	16 },
105		{ "abcdefg" "\xff\xff\xff\xff\xff\xff\xff\xff" "h",	16 },
106		{ "abcdefgh" "\xff\xff\xff\xff\xff\xff\xff\xff" "",	16 },
107	};
108
109	/*
110	 * During testing it is useful have the rest of the program
111	 * use a known good version!
112	 */
113#ifdef	__FreeBSD__
114	dl_handle = dlopen(NULL, RTLD_LAZY);
115	strlen_fn = dlsym(dl_handle, "test_strlen");
116#else
117	strlen_fn = dlsym(dlopen(NULL, RTLD_LAZY), "test_strlen");
118#endif
119	if (!strlen_fn)
120		strlen_fn = strlen;
121
122	for (a = 0; a < sizeof(long); ++a) {
123		for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) {
124
125			memcpy(&buf[a], tab[t].val, tab[t].len + 1);
126			len = strlen_fn(&buf[a]);
127
128			if (len != tab[t].len) {
129				/* Write error without using printf / strlen */
130				write(2, "alignment ", 10);
131				write_num(a);
132				write(2, ", test ", 7);
133				write_num(t);
134				write(2, ", got len ", 10);
135				write_num(len);
136				write(2, ", not ", 6);
137				write_num(tab[t].len);
138				write(2, ", for '", 7);
139				write(2, tab[t].val, tab[t].len);
140				write(2, "'\n", 2);
141				atf_tc_fail("See stderr for details");
142			}
143		}
144	}
145#ifdef	__FreeBSD__
146	(void)dlclose(dl_handle);
147#endif
148}
149
150ATF_TC(strlen_huge);
151ATF_TC_HEAD(strlen_huge, tc)
152{
153        atf_tc_set_md_var(tc, "descr", "Test strlen(3) with huge strings");
154}
155
156ATF_TC_BODY(strlen_huge, tc)
157{
158	long page;
159	char *str;
160	size_t i;
161
162	page = sysconf(_SC_PAGESIZE);
163	ATF_REQUIRE(page >= 0);
164
165	for (i = 1; i < 1000; i = i + 100) {
166
167		str = malloc(i * page + 1);
168
169		if (str == NULL)
170			continue;
171
172		(void)memset(str, 'x', i * page);
173		str[i * page] = '\0';
174
175		ATF_REQUIRE(strlen(str) == i * page);
176		free(str);
177	}
178}
179
180ATF_TC(strnlen_basic);
181ATF_TC_HEAD(strnlen_basic, tc)
182{
183        atf_tc_set_md_var(tc, "descr", "A naive test of strnlen(3)");
184}
185
186ATF_TC_BODY(strnlen_basic, tc)
187{
188	char buf[1];
189
190	buf[0] = '\0';
191
192	ATF_CHECK(strnlen(buf, 000) == 0);
193	ATF_CHECK(strnlen(buf, 111) == 0);
194
195	ATF_CHECK(strnlen("xxx", 0) == 0);
196	ATF_CHECK(strnlen("xxx", 1) == 1);
197	ATF_CHECK(strnlen("xxx", 2) == 2);
198	ATF_CHECK(strnlen("xxx", 3) == 3);
199	ATF_CHECK(strnlen("xxx", 9) == 3);
200}
201
202ATF_TP_ADD_TCS(tp)
203{
204
205	ATF_TP_ADD_TC(tp, strlen_basic);
206	ATF_TP_ADD_TC(tp, strlen_huge);
207	ATF_TP_ADD_TC(tp, strnlen_basic);
208
209	return atf_no_error();
210}
211