xref: /freebsd/contrib/netbsd-tests/lib/libc/string/t_strlen.c (revision 792bbaba989533a1fc93823df1720c8c4aaf0442)
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 
16 static void	write_num(int);
17 
18 static void
19 write_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 
35 ATF_TC(strlen_basic);
36 ATF_TC_HEAD(strlen_basic, tc)
37 {
38         atf_tc_set_md_var(tc, "descr", "Test strlen(3) results");
39 }
40 
41 ATF_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 
150 ATF_TC(strlen_huge);
151 ATF_TC_HEAD(strlen_huge, tc)
152 {
153         atf_tc_set_md_var(tc, "descr", "Test strlen(3) with huge strings");
154 }
155 
156 ATF_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 
180 ATF_TC(strnlen_basic);
181 ATF_TC_HEAD(strnlen_basic, tc)
182 {
183         atf_tc_set_md_var(tc, "descr", "A naive test of strnlen(3)");
184 }
185 
186 ATF_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 
202 ATF_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