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