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?
32 void check_memchr(void);
37 /* try to trick the compiler */
38 void * (*f
)(const void *, int, size_t) = memchr
;
52 const struct tab tab
[] = {
61 { "/abcde", 6, 1, 0 },
62 { "/abcdef", 7, 1, 0 },
63 { "/abcdefg", 8, 1, 0 },
70 { "a/bcde", 6, 1, 1 },
71 { "a/bcdef", 7, 1, 1 },
72 { "a/bcdefg", 8, 1, 1 },
78 { "ab/cde", 6, 1, 2 },
79 { "ab/cdef", 7, 1, 2 },
80 { "ab/cdefg", 8, 1, 2 },
85 { "abc/de", 6, 1, 3 },
86 { "abc/def", 7, 1, 3 },
87 { "abc/defg", 8, 1, 3 },
91 { "abcd/e", 6, 1, 4 },
92 { "abcd/ef", 7, 1, 4 },
93 { "abcd/efg", 8, 1, 4 },
95 { "abcde/", 5, 0, 0 },
96 { "abcde/", 6, 1, 5 },
97 { "abcde/f", 7, 1, 5 },
98 { "abcde/fg", 8, 1, 5 },
100 { "abcdef/", 6, 0, 0 },
101 { "abcdef/", 7, 1, 6 },
102 { "abcdef/g", 8, 1, 6 },
104 { "abcdefg/", 7, 0, 0 },
105 { "abcdefg/", 8, 1, 7 },
107 { "\xff\xff\xff\xff" "efg/", 8, 1, 7 },
108 { "a" "\xff\xff\xff\xff" "fg/", 8, 1, 7 },
109 { "ab" "\xff\xff\xff\xff" "g/", 8, 1, 7 },
110 { "abc" "\xff\xff\xff\xff" "/", 8, 1, 7 },
113 for (a
= 1; a
< 1 + sizeof(long); ++a
) {
114 for (t
= 0; t
< (sizeof(tab
) / sizeof(tab
[0])); ++t
) {
116 strcpy(&buf
[a
], tab
[t
].val
);
118 off
= f(&buf
[a
], '/', tab
[t
].len
);
119 assert((tab
[t
].match
== 0 && off
== 0) ||
120 (tab
[t
].match
== 1 && (tab
[t
].off
== ((char*)off
- &buf
[a
]))));
122 // check zero extension of char arg
123 off
= f(&buf
[a
], 0xffffff00 | '/', tab
[t
].len
);
124 assert((tab
[t
].match
== 0 && off
== 0) ||
125 (tab
[t
].match
== 1 && (tab
[t
].off
== ((char*)off
- &buf
[a
]))));