xref: /netbsd-src/tests/lib/libc/string/t_strchrnul.c (revision e20f737644f47900246981f10cc4584e92e67bc3)
1*e20f7376Schristos /* $NetBSD: t_strchrnul.c,v 1.1 2023/01/30 19:49:49 christos Exp $ */
2*e20f7376Schristos 
3*e20f7376Schristos /*
4*e20f7376Schristos  * Written by J.T. Conklin <jtc@acorntoolworks.com>
5*e20f7376Schristos  * Public domain.
6*e20f7376Schristos  */
7*e20f7376Schristos 
8*e20f7376Schristos #include <atf-c.h>
9*e20f7376Schristos #include <string.h>
10*e20f7376Schristos #include <unistd.h>
11*e20f7376Schristos #include <stdio.h>
12*e20f7376Schristos #include <stdlib.h>
13*e20f7376Schristos #include <dlfcn.h>
14*e20f7376Schristos 
15*e20f7376Schristos static char	*slow_strchrnul(char *, int);
16*e20f7376Schristos static void	 verify_strchrnul(char *, int, unsigned int, unsigned int);
17*e20f7376Schristos 
18*e20f7376Schristos char * (*volatile strchrnul_fn)(const char *, int);
19*e20f7376Schristos 
20*e20f7376Schristos static char *
slow_strchrnul(char * buf,int ch)21*e20f7376Schristos slow_strchrnul(char *buf, int ch)
22*e20f7376Schristos {
23*e20f7376Schristos 	unsigned char c = 1;
24*e20f7376Schristos 
25*e20f7376Schristos 	ch &= 0xff;
26*e20f7376Schristos 
27*e20f7376Schristos 	for (; ; buf++) {
28*e20f7376Schristos 		c = *buf;
29*e20f7376Schristos 		if (c == ch || c == 0)
30*e20f7376Schristos 			return buf;
31*e20f7376Schristos 	}
32*e20f7376Schristos }
33*e20f7376Schristos 
34*e20f7376Schristos static void
verify_strchrnul(char * buf,int ch,unsigned int t,unsigned int a)35*e20f7376Schristos verify_strchrnul(char *buf, int ch, unsigned int t, unsigned int a)
36*e20f7376Schristos {
37*e20f7376Schristos 	const char *off, *ok_off;
38*e20f7376Schristos 
39*e20f7376Schristos 	off = strchrnul_fn(buf, ch);
40*e20f7376Schristos 	ok_off = slow_strchrnul(buf, ch);
41*e20f7376Schristos 	if (off == ok_off)
42*e20f7376Schristos 		return;
43*e20f7376Schristos 
44*e20f7376Schristos 	fprintf(stderr, "test_strchrnul(\"%s\", %#x) gave %zd not %zd (test %d, "
45*e20f7376Schristos 	    "alignment %d)\n",
46*e20f7376Schristos 	    buf, ch, off ? off - buf : -1, ok_off ? ok_off - buf : -1, t, a);
47*e20f7376Schristos 
48*e20f7376Schristos 	atf_tc_fail("Check stderr for details");
49*e20f7376Schristos }
50*e20f7376Schristos 
51*e20f7376Schristos ATF_TC(strchrnul_basic);
ATF_TC_HEAD(strchrnul_basic,tc)52*e20f7376Schristos ATF_TC_HEAD(strchrnul_basic, tc)
53*e20f7376Schristos {
54*e20f7376Schristos 
55*e20f7376Schristos         atf_tc_set_md_var(tc, "descr", "Test strchrnul(3) results");
56*e20f7376Schristos }
57*e20f7376Schristos 
ATF_TC_BODY(strchrnul_basic,tc)58*e20f7376Schristos ATF_TC_BODY(strchrnul_basic, tc)
59*e20f7376Schristos {
60*e20f7376Schristos 	void *dl_handle;
61*e20f7376Schristos 	char *off;
62*e20f7376Schristos 	char buf[32];
63*e20f7376Schristos 	unsigned int t, a;
64*e20f7376Schristos 
65*e20f7376Schristos 	const char *tab[] = {
66*e20f7376Schristos 		"",
67*e20f7376Schristos 		"a",
68*e20f7376Schristos 		"aa",
69*e20f7376Schristos 		"abc",
70*e20f7376Schristos 		"abcd",
71*e20f7376Schristos 		"abcde",
72*e20f7376Schristos 		"abcdef",
73*e20f7376Schristos 		"abcdefg",
74*e20f7376Schristos 		"abcdefgh",
75*e20f7376Schristos 
76*e20f7376Schristos 		"/",
77*e20f7376Schristos 		"//",
78*e20f7376Schristos 		"/a",
79*e20f7376Schristos 		"/a/",
80*e20f7376Schristos 		"/ab",
81*e20f7376Schristos 		"/ab/",
82*e20f7376Schristos 		"/abc",
83*e20f7376Schristos 		"/abc/",
84*e20f7376Schristos 		"/abcd",
85*e20f7376Schristos 		"/abcd/",
86*e20f7376Schristos 		"/abcde",
87*e20f7376Schristos 		"/abcde/",
88*e20f7376Schristos 		"/abcdef",
89*e20f7376Schristos 		"/abcdef/",
90*e20f7376Schristos 		"/abcdefg",
91*e20f7376Schristos 		"/abcdefg/",
92*e20f7376Schristos 		"/abcdefgh",
93*e20f7376Schristos 		"/abcdefgh/",
94*e20f7376Schristos 
95*e20f7376Schristos 		"a/",
96*e20f7376Schristos 		"a//",
97*e20f7376Schristos 		"a/a",
98*e20f7376Schristos 		"a/a/",
99*e20f7376Schristos 		"a/ab",
100*e20f7376Schristos 		"a/ab/",
101*e20f7376Schristos 		"a/abc",
102*e20f7376Schristos 		"a/abc/",
103*e20f7376Schristos 		"a/abcd",
104*e20f7376Schristos 		"a/abcd/",
105*e20f7376Schristos 		"a/abcde",
106*e20f7376Schristos 		"a/abcde/",
107*e20f7376Schristos 		"a/abcdef",
108*e20f7376Schristos 		"a/abcdef/",
109*e20f7376Schristos 		"a/abcdefg",
110*e20f7376Schristos 		"a/abcdefg/",
111*e20f7376Schristos 		"a/abcdefgh",
112*e20f7376Schristos 		"a/abcdefgh/",
113*e20f7376Schristos 
114*e20f7376Schristos 		"ab/",
115*e20f7376Schristos 		"ab//",
116*e20f7376Schristos 		"ab/a",
117*e20f7376Schristos 		"ab/a/",
118*e20f7376Schristos 		"ab/ab",
119*e20f7376Schristos 		"ab/ab/",
120*e20f7376Schristos 		"ab/abc",
121*e20f7376Schristos 		"ab/abc/",
122*e20f7376Schristos 		"ab/abcd",
123*e20f7376Schristos 		"ab/abcd/",
124*e20f7376Schristos 		"ab/abcde",
125*e20f7376Schristos 		"ab/abcde/",
126*e20f7376Schristos 		"ab/abcdef",
127*e20f7376Schristos 		"ab/abcdef/",
128*e20f7376Schristos 		"ab/abcdefg",
129*e20f7376Schristos 		"ab/abcdefg/",
130*e20f7376Schristos 		"ab/abcdefgh",
131*e20f7376Schristos 		"ab/abcdefgh/",
132*e20f7376Schristos 
133*e20f7376Schristos 		"abc/",
134*e20f7376Schristos 		"abc//",
135*e20f7376Schristos 		"abc/a",
136*e20f7376Schristos 		"abc/a/",
137*e20f7376Schristos 		"abc/ab",
138*e20f7376Schristos 		"abc/ab/",
139*e20f7376Schristos 		"abc/abc",
140*e20f7376Schristos 		"abc/abc/",
141*e20f7376Schristos 		"abc/abcd",
142*e20f7376Schristos 		"abc/abcd/",
143*e20f7376Schristos 		"abc/abcde",
144*e20f7376Schristos 		"abc/abcde/",
145*e20f7376Schristos 		"abc/abcdef",
146*e20f7376Schristos 		"abc/abcdef/",
147*e20f7376Schristos 		"abc/abcdefg",
148*e20f7376Schristos 		"abc/abcdefg/",
149*e20f7376Schristos 		"abc/abcdefgh",
150*e20f7376Schristos 		"abc/abcdefgh/",
151*e20f7376Schristos 
152*e20f7376Schristos 		"abcd/",
153*e20f7376Schristos 		"abcd//",
154*e20f7376Schristos 		"abcd/a",
155*e20f7376Schristos 		"abcd/a/",
156*e20f7376Schristos 		"abcd/ab",
157*e20f7376Schristos 		"abcd/ab/",
158*e20f7376Schristos 		"abcd/abc",
159*e20f7376Schristos 		"abcd/abc/",
160*e20f7376Schristos 		"abcd/abcd",
161*e20f7376Schristos 		"abcd/abcd/",
162*e20f7376Schristos 		"abcd/abcde",
163*e20f7376Schristos 		"abcd/abcde/",
164*e20f7376Schristos 		"abcd/abcdef",
165*e20f7376Schristos 		"abcd/abcdef/",
166*e20f7376Schristos 		"abcd/abcdefg",
167*e20f7376Schristos 		"abcd/abcdefg/",
168*e20f7376Schristos 		"abcd/abcdefgh",
169*e20f7376Schristos 		"abcd/abcdefgh/",
170*e20f7376Schristos 
171*e20f7376Schristos 		"abcde/",
172*e20f7376Schristos 		"abcde//",
173*e20f7376Schristos 		"abcde/a",
174*e20f7376Schristos 		"abcde/a/",
175*e20f7376Schristos 		"abcde/ab",
176*e20f7376Schristos 		"abcde/ab/",
177*e20f7376Schristos 		"abcde/abc",
178*e20f7376Schristos 		"abcde/abc/",
179*e20f7376Schristos 		"abcde/abcd",
180*e20f7376Schristos 		"abcde/abcd/",
181*e20f7376Schristos 		"abcde/abcde",
182*e20f7376Schristos 		"abcde/abcde/",
183*e20f7376Schristos 		"abcde/abcdef",
184*e20f7376Schristos 		"abcde/abcdef/",
185*e20f7376Schristos 		"abcde/abcdefg",
186*e20f7376Schristos 		"abcde/abcdefg/",
187*e20f7376Schristos 		"abcde/abcdefgh",
188*e20f7376Schristos 		"abcde/abcdefgh/",
189*e20f7376Schristos 
190*e20f7376Schristos 		"abcdef/",
191*e20f7376Schristos 		"abcdef//",
192*e20f7376Schristos 		"abcdef/a",
193*e20f7376Schristos 		"abcdef/a/",
194*e20f7376Schristos 		"abcdef/ab",
195*e20f7376Schristos 		"abcdef/ab/",
196*e20f7376Schristos 		"abcdef/abc",
197*e20f7376Schristos 		"abcdef/abc/",
198*e20f7376Schristos 		"abcdef/abcd",
199*e20f7376Schristos 		"abcdef/abcd/",
200*e20f7376Schristos 		"abcdef/abcde",
201*e20f7376Schristos 		"abcdef/abcde/",
202*e20f7376Schristos 		"abcdef/abcdef",
203*e20f7376Schristos 		"abcdef/abcdef/",
204*e20f7376Schristos 		"abcdef/abcdefg",
205*e20f7376Schristos 		"abcdef/abcdefg/",
206*e20f7376Schristos 		"abcdef/abcdefgh",
207*e20f7376Schristos 		"abcdef/abcdefgh/",
208*e20f7376Schristos 
209*e20f7376Schristos 		"abcdefg/",
210*e20f7376Schristos 		"abcdefg//",
211*e20f7376Schristos 		"abcdefg/a",
212*e20f7376Schristos 		"abcdefg/a/",
213*e20f7376Schristos 		"abcdefg/ab",
214*e20f7376Schristos 		"abcdefg/ab/",
215*e20f7376Schristos 		"abcdefg/abc",
216*e20f7376Schristos 		"abcdefg/abc/",
217*e20f7376Schristos 		"abcdefg/abcd",
218*e20f7376Schristos 		"abcdefg/abcd/",
219*e20f7376Schristos 		"abcdefg/abcde",
220*e20f7376Schristos 		"abcdefg/abcde/",
221*e20f7376Schristos 		"abcdefg/abcdef",
222*e20f7376Schristos 		"abcdefg/abcdef/",
223*e20f7376Schristos 		"abcdefg/abcdefg",
224*e20f7376Schristos 		"abcdefg/abcdefg/",
225*e20f7376Schristos 		"abcdefg/abcdefgh",
226*e20f7376Schristos 		"abcdefg/abcdefgh/",
227*e20f7376Schristos 
228*e20f7376Schristos 		"abcdefgh/",
229*e20f7376Schristos 		"abcdefgh//",
230*e20f7376Schristos 		"abcdefgh/a",
231*e20f7376Schristos 		"abcdefgh/a/",
232*e20f7376Schristos 		"abcdefgh/ab",
233*e20f7376Schristos 		"abcdefgh/ab/",
234*e20f7376Schristos 		"abcdefgh/abc",
235*e20f7376Schristos 		"abcdefgh/abc/",
236*e20f7376Schristos 		"abcdefgh/abcd",
237*e20f7376Schristos 		"abcdefgh/abcd/",
238*e20f7376Schristos 		"abcdefgh/abcde",
239*e20f7376Schristos 		"abcdefgh/abcde/",
240*e20f7376Schristos 		"abcdefgh/abcdef",
241*e20f7376Schristos 		"abcdefgh/abcdef/",
242*e20f7376Schristos 		"abcdefgh/abcdefg",
243*e20f7376Schristos 		"abcdefgh/abcdefg/",
244*e20f7376Schristos 		"abcdefgh/abcdefgh",
245*e20f7376Schristos 		"abcdefgh/abcdefgh/",
246*e20f7376Schristos 	};
247*e20f7376Schristos 
248*e20f7376Schristos 	dl_handle = dlopen(NULL, RTLD_LAZY);
249*e20f7376Schristos 	strchrnul_fn = dlsym(dl_handle, "test_strchrnul");
250*e20f7376Schristos 	if (!strchrnul_fn)
251*e20f7376Schristos 		strchrnul_fn = strchrnul;
252*e20f7376Schristos 
253*e20f7376Schristos 	for (a = 3; a < 3 + sizeof(long); ++a) {
254*e20f7376Schristos 		/* Put char and a \0 before the buffer */
255*e20f7376Schristos 		buf[a-1] = '/';
256*e20f7376Schristos 		buf[a-2] = '0';
257*e20f7376Schristos 		buf[a-3] = 0xff;
258*e20f7376Schristos 		for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) {
259*e20f7376Schristos 			int len = strlen(tab[t]) + 1;
260*e20f7376Schristos 			memcpy(&buf[a], tab[t], len);
261*e20f7376Schristos 
262*e20f7376Schristos 			/* Put the char we are looking for after the \0 */
263*e20f7376Schristos 			buf[a + len] = '/';
264*e20f7376Schristos 
265*e20f7376Schristos 			/* Check search for NUL at end of string */
266*e20f7376Schristos 			verify_strchrnul(buf + a, 0, t, a);
267*e20f7376Schristos 
268*e20f7376Schristos 			/* Then for the '/' in the strings */
269*e20f7376Schristos 			verify_strchrnul(buf + a, '/', t, a);
270*e20f7376Schristos 
271*e20f7376Schristos 			/* check zero extension of char arg */
272*e20f7376Schristos 			verify_strchrnul(buf + a, 0xffffff00 | '/', t, a);
273*e20f7376Schristos 
274*e20f7376Schristos 			/* Replace all the '/' with 0xff */
275*e20f7376Schristos 			while (*(off = slow_strchrnul(buf + a, '/')) != '\0')
276*e20f7376Schristos 				*off = 0xff;
277*e20f7376Schristos 
278*e20f7376Schristos 			buf[a + len] = 0xff;
279*e20f7376Schristos 
280*e20f7376Schristos 			/* Check we can search for 0xff as well as '/' */
281*e20f7376Schristos 			verify_strchrnul(buf + a, 0xff, t, a);
282*e20f7376Schristos 		}
283*e20f7376Schristos 	}
284*e20f7376Schristos 	(void)dlclose(dl_handle);
285*e20f7376Schristos }
286*e20f7376Schristos 
ATF_TP_ADD_TCS(tp)287*e20f7376Schristos ATF_TP_ADD_TCS(tp)
288*e20f7376Schristos {
289*e20f7376Schristos 
290*e20f7376Schristos 	ATF_TP_ADD_TC(tp, strchrnul_basic);
291*e20f7376Schristos 
292*e20f7376Schristos 	return atf_no_error();
293*e20f7376Schristos }
294