2 * Written by J.T. Conklin <jtc@acorntoolworks.com>
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.
16 * Misssing checks for strncpy, strncat, strncmp, etc.
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?
35 char * (*volatile strchr_fn
)(const char *, int);
41 slow_strchr(char *buf
, int ch
)
47 for (; c
!= 0; buf
++) {
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
);
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
);
257 "abcdefgh/abcdefgh/",
261 for (a
= 3; a
< 3 + sizeof(long); ++a
) {
262 /* Put char and a \0 before the buffer */
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 */
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
)
286 /* Check we can search for 0xff as well as '/' */
287 verify_strchr(buf
+ a
, 0xff);
295 strchr_fn
= dlsym(dlopen(0, RTLD_LAZY
), "test_strchr");