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