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