Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / regress / lib / libc / string / strchr / strchr_test.c
blob11f6610ac7865f29b942868ba95866f83bdf8d35
1 /*
2 * Written by J.T. Conklin <jtc@acorntoolworks.com>
3 * Public domain.
4 */
6 /*
7 * str*() regression suite
9 * Trivial str*() implementations can be audited by hand. Optimized
10 * versions that unroll loops, use naturally-aligned memory acesses,
11 * and "magic" arithmetic sequences to detect zero-bytes, written in
12 * assembler are much harder to validate. This program attempts to
13 * catch the corner cases.
15 * BUGS:
16 * Misssing checks for strncpy, strncat, strncmp, etc.
18 * TODO:
19 * Use mmap/mprotect to ensure the functions don't access memory
20 * across page boundaries.
22 * Consider generating tables programmatically. It would reduce
23 * the size, but it's also one more thing to go wrong.
25 * Share tables between strlen, strcpy, and strcat?
26 * Share tables between strchr and strrchr?
29 #include <assert.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <dlfcn.h>
35 char * (*volatile strchr_fn)(const char *, int);
37 static int a;
38 static int t;
40 static char *
41 slow_strchr(char *buf, int ch)
43 unsigned char c = 1;
45 ch &= 0xff;
47 for (; c != 0; buf++) {
48 c = *buf;
49 if (c == ch)
50 return buf;
52 return 0;
55 static void
56 verify_strchr(char *buf, int ch)
58 const char *off, *ok_off;
60 off = strchr_fn(buf, ch);
61 ok_off = slow_strchr(buf, ch);
62 if (off == ok_off)
63 return;
65 fprintf(stderr, "test_strchr(\"%s\", %#x) gave %zd not %zd (test %d, alignment %d)\n",
66 buf, ch, off ? off - buf : -1, ok_off ? ok_off - buf : -1, t, a);
68 exit(1);
71 static void
72 check_strchr(void)
74 char *off;
75 char buf[32];
77 const char *tab[] = {
78 "",
79 "a",
80 "aa",
81 "abc",
82 "abcd",
83 "abcde",
84 "abcdef",
85 "abcdefg",
86 "abcdefgh",
88 "/",
89 "//",
90 "/a",
91 "/a/",
92 "/ab",
93 "/ab/",
94 "/abc",
95 "/abc/",
96 "/abcd",
97 "/abcd/",
98 "/abcde",
99 "/abcde/",
100 "/abcdef",
101 "/abcdef/",
102 "/abcdefg",
103 "/abcdefg/",
104 "/abcdefgh",
105 "/abcdefgh/",
107 "a/",
108 "a//",
109 "a/a",
110 "a/a/",
111 "a/ab",
112 "a/ab/",
113 "a/abc",
114 "a/abc/",
115 "a/abcd",
116 "a/abcd/",
117 "a/abcde",
118 "a/abcde/",
119 "a/abcdef",
120 "a/abcdef/",
121 "a/abcdefg",
122 "a/abcdefg/",
123 "a/abcdefgh",
124 "a/abcdefgh/",
126 "ab/",
127 "ab//",
128 "ab/a",
129 "ab/a/",
130 "ab/ab",
131 "ab/ab/",
132 "ab/abc",
133 "ab/abc/",
134 "ab/abcd",
135 "ab/abcd/",
136 "ab/abcde",
137 "ab/abcde/",
138 "ab/abcdef",
139 "ab/abcdef/",
140 "ab/abcdefg",
141 "ab/abcdefg/",
142 "ab/abcdefgh",
143 "ab/abcdefgh/",
145 "abc/",
146 "abc//",
147 "abc/a",
148 "abc/a/",
149 "abc/ab",
150 "abc/ab/",
151 "abc/abc",
152 "abc/abc/",
153 "abc/abcd",
154 "abc/abcd/",
155 "abc/abcde",
156 "abc/abcde/",
157 "abc/abcdef",
158 "abc/abcdef/",
159 "abc/abcdefg",
160 "abc/abcdefg/",
161 "abc/abcdefgh",
162 "abc/abcdefgh/",
164 "abcd/",
165 "abcd//",
166 "abcd/a",
167 "abcd/a/",
168 "abcd/ab",
169 "abcd/ab/",
170 "abcd/abc",
171 "abcd/abc/",
172 "abcd/abcd",
173 "abcd/abcd/",
174 "abcd/abcde",
175 "abcd/abcde/",
176 "abcd/abcdef",
177 "abcd/abcdef/",
178 "abcd/abcdefg",
179 "abcd/abcdefg/",
180 "abcd/abcdefgh",
181 "abcd/abcdefgh/",
183 "abcde/",
184 "abcde//",
185 "abcde/a",
186 "abcde/a/",
187 "abcde/ab",
188 "abcde/ab/",
189 "abcde/abc",
190 "abcde/abc/",
191 "abcde/abcd",
192 "abcde/abcd/",
193 "abcde/abcde",
194 "abcde/abcde/",
195 "abcde/abcdef",
196 "abcde/abcdef/",
197 "abcde/abcdefg",
198 "abcde/abcdefg/",
199 "abcde/abcdefgh",
200 "abcde/abcdefgh/",
202 "abcdef/",
203 "abcdef//",
204 "abcdef/a",
205 "abcdef/a/",
206 "abcdef/ab",
207 "abcdef/ab/",
208 "abcdef/abc",
209 "abcdef/abc/",
210 "abcdef/abcd",
211 "abcdef/abcd/",
212 "abcdef/abcde",
213 "abcdef/abcde/",
214 "abcdef/abcdef",
215 "abcdef/abcdef/",
216 "abcdef/abcdefg",
217 "abcdef/abcdefg/",
218 "abcdef/abcdefgh",
219 "abcdef/abcdefgh/",
221 "abcdefg/",
222 "abcdefg//",
223 "abcdefg/a",
224 "abcdefg/a/",
225 "abcdefg/ab",
226 "abcdefg/ab/",
227 "abcdefg/abc",
228 "abcdefg/abc/",
229 "abcdefg/abcd",
230 "abcdefg/abcd/",
231 "abcdefg/abcde",
232 "abcdefg/abcde/",
233 "abcdefg/abcdef",
234 "abcdefg/abcdef/",
235 "abcdefg/abcdefg",
236 "abcdefg/abcdefg/",
237 "abcdefg/abcdefgh",
238 "abcdefg/abcdefgh/",
240 "abcdefgh/",
241 "abcdefgh//",
242 "abcdefgh/a",
243 "abcdefgh/a/",
244 "abcdefgh/ab",
245 "abcdefgh/ab/",
246 "abcdefgh/abc",
247 "abcdefgh/abc/",
248 "abcdefgh/abcd",
249 "abcdefgh/abcd/",
250 "abcdefgh/abcde",
251 "abcdefgh/abcde/",
252 "abcdefgh/abcdef",
253 "abcdefgh/abcdef/",
254 "abcdefgh/abcdefg",
255 "abcdefgh/abcdefg/",
256 "abcdefgh/abcdefgh",
257 "abcdefgh/abcdefgh/",
261 for (a = 3; a < 3 + sizeof(long); ++a) {
262 /* Put char and a \0 before the buffer */
263 buf[a-1] = '/';
264 buf[a-2] = '0';
265 buf[a-3] = 0xff;
266 for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) {
267 int len = strlen(tab[t]) + 1;
268 memcpy(&buf[a], tab[t], len);
269 /* Put the char we are looking for after the \0 */
270 buf[a + len] = '/';
272 /* Check search for NUL at end of string */
273 verify_strchr(buf + a, 0);
275 /* Then for the '/' in the strings */
276 verify_strchr(buf + a, '/');
278 /* check zero extension of char arg */
279 verify_strchr(buf + a, 0xffffff00 | '/');
281 /* Replace all the '/' with 0xff */
282 while ((off = slow_strchr(buf + a, '/')) != NULL)
283 *off = 0xff;
284 buf[a + len] = 0xff;
286 /* Check we can search for 0xff as well as '/' */
287 verify_strchr(buf + a, 0xff);
293 main(void)
295 strchr_fn = dlsym(dlopen(0, RTLD_LAZY), "test_strchr");
296 if (!strchr_fn)
297 strchr_fn = strchr;
298 check_strchr();
299 return 0;