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_strrchr(void);
37 /* try to trick the compiler */
38 char * (*f
)(const char *, int) = strrchr
;
48 size_t f_off
; /* offset of first match */
49 size_t l_off
; /* offset of last match */
52 const struct tab tab
[] = {
59 { "abcdef", 0, 0, 0 },
60 { "abcdefg", 0, 0, 0 },
61 { "abcdefgh", 0, 0, 0 },
72 { "/abcd/", 1, 0, 5 },
73 { "/abcde", 1, 0, 0 },
74 { "/abcde/", 1, 0, 6 },
75 { "/abcdef", 1, 0, 0 },
76 { "/abcdef/", 1, 0, 7 },
77 { "/abcdefg", 1, 0, 0 },
78 { "/abcdefg/", 1, 0, 8 },
79 { "/abcdefgh", 1, 0, 0 },
80 { "/abcdefgh/", 1, 0, 9 },
89 { "a/abc/", 1, 1, 5 },
90 { "a/abcd", 1, 1, 1 },
91 { "a/abcd/", 1, 1, 6 },
92 { "a/abcde", 1, 1, 1 },
93 { "a/abcde/", 1, 1, 7 },
94 { "a/abcdef", 1, 1, 1 },
95 { "a/abcdef/", 1, 1, 8 },
96 { "a/abcdefg", 1, 1, 1 },
97 { "a/abcdefg/", 1, 1, 9 },
98 { "a/abcdefgh", 1, 1, 1 },
99 { "a/abcdefgh/", 1, 1, 10 },
104 { "ab/a/", 1, 2, 4 },
105 { "ab/ab", 1, 2, 2 },
106 { "ab/ab/", 1, 2, 5 },
107 { "ab/abc", 1, 2, 2 },
108 { "ab/abc/", 1, 2, 6 },
109 { "ab/abcd", 1, 2, 2 },
110 { "ab/abcd/", 1, 2, 7 },
111 { "ab/abcde", 1, 2, 2 },
112 { "ab/abcde/", 1, 2, 8 },
113 { "ab/abcdef", 1, 2, 2 },
114 { "ab/abcdef/", 1, 2, 9 },
115 { "ab/abcdefg", 1, 2, 2 },
116 { "ab/abcdefg/", 1, 2, 10 },
117 { "ab/abcdefgh", 1, 2, 2 },
118 { "ab/abcdefgh/", 1, 2, 11 },
121 { "abc//", 1, 3, 4 },
122 { "abc/a", 1, 3, 3 },
123 { "abc/a/", 1, 3, 5 },
124 { "abc/ab", 1, 3, 3 },
125 { "abc/ab/", 1, 3, 6 },
126 { "abc/abc", 1, 3, 3 },
127 { "abc/abc/", 1, 3, 7 },
128 { "abc/abcd", 1, 3, 3 },
129 { "abc/abcd/", 1, 3, 8 },
130 { "abc/abcde", 1, 3, 3 },
131 { "abc/abcde/", 1, 3, 9 },
132 { "abc/abcdef", 1, 3, 3 },
133 { "abc/abcdef/", 1, 3, 10 },
134 { "abc/abcdefg", 1, 3, 3 },
135 { "abc/abcdefg/", 1, 3, 11 },
136 { "abc/abcdefgh", 1, 3, 3 },
137 { "abc/abcdefgh/", 1, 3, 12 },
139 { "abcd/", 1, 4, 4 },
140 { "abcd//", 1, 4, 5 },
141 { "abcd/a", 1, 4, 4 },
142 { "abcd/a/", 1, 4, 6 },
143 { "abcd/ab", 1, 4, 4 },
144 { "abcd/ab/", 1, 4, 7 },
145 { "abcd/abc", 1, 4, 4 },
146 { "abcd/abc/", 1, 4, 8 },
147 { "abcd/abcd", 1, 4, 4 },
148 { "abcd/abcd/", 1, 4, 9 },
149 { "abcd/abcde", 1, 4, 4 },
150 { "abcd/abcde/", 1, 4, 10 },
151 { "abcd/abcdef", 1, 4, 4 },
152 { "abcd/abcdef/", 1, 4, 11 },
153 { "abcd/abcdefg", 1, 4, 4 },
154 { "abcd/abcdefg/", 1, 4, 12 },
155 { "abcd/abcdefgh", 1, 4, 4 },
156 { "abcd/abcdefgh/", 1, 4, 13 },
158 { "abcde/", 1, 5, 5 },
159 { "abcde//", 1, 5, 6 },
160 { "abcde/a", 1, 5, 5 },
161 { "abcde/a/", 1, 5, 7 },
162 { "abcde/ab", 1, 5, 5 },
163 { "abcde/ab/", 1, 5, 8 },
164 { "abcde/abc", 1, 5, 5 },
165 { "abcde/abc/", 1, 5, 9 },
166 { "abcde/abcd", 1, 5, 5 },
167 { "abcde/abcd/", 1, 5, 10 },
168 { "abcde/abcde", 1, 5, 5 },
169 { "abcde/abcde/", 1, 5, 11 },
170 { "abcde/abcdef", 1, 5, 5 },
171 { "abcde/abcdef/", 1, 5, 12 },
172 { "abcde/abcdefg", 1, 5, 5 },
173 { "abcde/abcdefg/", 1, 5, 13 },
174 { "abcde/abcdefgh", 1, 5, 5 },
175 { "abcde/abcdefgh/", 1, 5, 14 },
177 { "abcdef/", 1, 6, 6 },
178 { "abcdef//", 1, 6, 7 },
179 { "abcdef/a", 1, 6, 6 },
180 { "abcdef/a/", 1, 6, 8 },
181 { "abcdef/ab", 1, 6, 6 },
182 { "abcdef/ab/", 1, 6, 9 },
183 { "abcdef/abc", 1, 6, 6 },
184 { "abcdef/abc/", 1, 6, 10 },
185 { "abcdef/abcd", 1, 6, 6 },
186 { "abcdef/abcd/", 1, 6, 11 },
187 { "abcdef/abcde", 1, 6, 6 },
188 { "abcdef/abcde/", 1, 6, 12 },
189 { "abcdef/abcdef", 1, 6, 6 },
190 { "abcdef/abcdef/", 1, 6, 13 },
191 { "abcdef/abcdefg", 1, 6, 6 },
192 { "abcdef/abcdefg/", 1, 6, 14 },
193 { "abcdef/abcdefgh", 1, 6, 6 },
194 { "abcdef/abcdefgh/", 1, 6, 15 },
196 { "abcdefg/", 1, 7, 7 },
197 { "abcdefg//", 1, 7, 8 },
198 { "abcdefg/a", 1, 7, 7 },
199 { "abcdefg/a/", 1, 7, 9 },
200 { "abcdefg/ab", 1, 7, 7 },
201 { "abcdefg/ab/", 1, 7, 10 },
202 { "abcdefg/abc", 1, 7, 7 },
203 { "abcdefg/abc/", 1, 7, 11 },
204 { "abcdefg/abcd", 1, 7, 7 },
205 { "abcdefg/abcd/", 1, 7, 12 },
206 { "abcdefg/abcde", 1, 7, 7 },
207 { "abcdefg/abcde/", 1, 7, 13 },
208 { "abcdefg/abcdef", 1, 7, 7 },
209 { "abcdefg/abcdef/", 1, 7, 14 },
210 { "abcdefg/abcdefg", 1, 7, 7 },
211 { "abcdefg/abcdefg/", 1, 7, 15 },
212 { "abcdefg/abcdefgh", 1, 7, 7 },
213 { "abcdefg/abcdefgh/", 1, 7, 16 },
215 { "abcdefgh/", 1, 8, 8 },
216 { "abcdefgh//", 1, 8, 9 },
217 { "abcdefgh/a", 1, 8, 8 },
218 { "abcdefgh/a/", 1, 8, 10 },
219 { "abcdefgh/ab", 1, 8, 8 },
220 { "abcdefgh/ab/", 1, 8, 11 },
221 { "abcdefgh/abc", 1, 8, 8 },
222 { "abcdefgh/abc/", 1, 8, 12 },
223 { "abcdefgh/abcd", 1, 8, 8 },
224 { "abcdefgh/abcd/", 1, 8, 13 },
225 { "abcdefgh/abcde", 1, 8, 8 },
226 { "abcdefgh/abcde/", 1, 8, 14 },
227 { "abcdefgh/abcdef", 1, 8, 8 },
228 { "abcdefgh/abcdef/", 1, 8, 15 },
229 { "abcdefgh/abcdefg", 1, 8, 8 },
230 { "abcdefgh/abcdefg/", 1, 8, 16 },
231 { "abcdefgh/abcdefgh", 1, 8, 8 },
232 { "abcdefgh/abcdefgh/", 1, 8, 17 },
235 for (a
= 0; a
< sizeof(long); ++a
) {
236 for (t
= 0; t
< (sizeof(tab
) / sizeof(tab
[0])); ++t
) {
237 strcpy(&buf
[a
], tab
[t
].val
);
239 off
= f(&buf
[a
], '/');
240 assert((tab
[t
].match
== 0 && off
== 0) ||
241 (tab
[t
].match
== 1 && (tab
[t
].l_off
== (off
- &buf
[a
]))));
243 // check zero extension of char arg
244 off
= f(&buf
[a
], 0xffffff00 | '/');
245 assert((tab
[t
].match
== 0 && off
== 0) ||
246 (tab
[t
].match
== 1 && (tab
[t
].l_off
== (off
- &buf
[a
]))));