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