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