1 /* $NetBSD: t_strchr.c,v 1.3 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_strchr(char *, int); 16 static void verify_strchr(char *, int, unsigned int, unsigned int); 17 18 char * (*volatile strchr_fn)(const char *, int); 19 20 static char * 21 slow_strchr(char *buf, int ch) 22 { 23 unsigned char c = 1; 24 25 ch &= 0xff; 26 27 for (; c != 0; buf++) { 28 c = *buf; 29 if (c == ch) 30 return buf; 31 } 32 return 0; 33 } 34 35 static void 36 verify_strchr(char *buf, int ch, unsigned int t, unsigned int a) 37 { 38 const char *off, *ok_off; 39 40 off = strchr_fn(buf, ch); 41 ok_off = slow_strchr(buf, ch); 42 if (off == ok_off) 43 return; 44 45 fprintf(stderr, "test_strchr(\"%s\", %#x) gave %zd not %zd (test %d, " 46 "alignment %d)\n", 47 buf, ch, off ? off - buf : -1, ok_off ? ok_off - buf : -1, t, a); 48 49 atf_tc_fail("Check stderr for details"); 50 } 51 52 ATF_TC(strchr_basic); 53 ATF_TC_HEAD(strchr_basic, tc) 54 { 55 56 atf_tc_set_md_var(tc, "descr", "Test strchr(3) results"); 57 } 58 59 ATF_TC_BODY(strchr_basic, tc) 60 { 61 void *dl_handle; 62 char *off; 63 char buf[32]; 64 unsigned int t, a; 65 66 const char *tab[] = { 67 "", 68 "a", 69 "aa", 70 "abc", 71 "abcd", 72 "abcde", 73 "abcdef", 74 "abcdefg", 75 "abcdefgh", 76 77 "/", 78 "//", 79 "/a", 80 "/a/", 81 "/ab", 82 "/ab/", 83 "/abc", 84 "/abc/", 85 "/abcd", 86 "/abcd/", 87 "/abcde", 88 "/abcde/", 89 "/abcdef", 90 "/abcdef/", 91 "/abcdefg", 92 "/abcdefg/", 93 "/abcdefgh", 94 "/abcdefgh/", 95 96 "a/", 97 "a//", 98 "a/a", 99 "a/a/", 100 "a/ab", 101 "a/ab/", 102 "a/abc", 103 "a/abc/", 104 "a/abcd", 105 "a/abcd/", 106 "a/abcde", 107 "a/abcde/", 108 "a/abcdef", 109 "a/abcdef/", 110 "a/abcdefg", 111 "a/abcdefg/", 112 "a/abcdefgh", 113 "a/abcdefgh/", 114 115 "ab/", 116 "ab//", 117 "ab/a", 118 "ab/a/", 119 "ab/ab", 120 "ab/ab/", 121 "ab/abc", 122 "ab/abc/", 123 "ab/abcd", 124 "ab/abcd/", 125 "ab/abcde", 126 "ab/abcde/", 127 "ab/abcdef", 128 "ab/abcdef/", 129 "ab/abcdefg", 130 "ab/abcdefg/", 131 "ab/abcdefgh", 132 "ab/abcdefgh/", 133 134 "abc/", 135 "abc//", 136 "abc/a", 137 "abc/a/", 138 "abc/ab", 139 "abc/ab/", 140 "abc/abc", 141 "abc/abc/", 142 "abc/abcd", 143 "abc/abcd/", 144 "abc/abcde", 145 "abc/abcde/", 146 "abc/abcdef", 147 "abc/abcdef/", 148 "abc/abcdefg", 149 "abc/abcdefg/", 150 "abc/abcdefgh", 151 "abc/abcdefgh/", 152 153 "abcd/", 154 "abcd//", 155 "abcd/a", 156 "abcd/a/", 157 "abcd/ab", 158 "abcd/ab/", 159 "abcd/abc", 160 "abcd/abc/", 161 "abcd/abcd", 162 "abcd/abcd/", 163 "abcd/abcde", 164 "abcd/abcde/", 165 "abcd/abcdef", 166 "abcd/abcdef/", 167 "abcd/abcdefg", 168 "abcd/abcdefg/", 169 "abcd/abcdefgh", 170 "abcd/abcdefgh/", 171 172 "abcde/", 173 "abcde//", 174 "abcde/a", 175 "abcde/a/", 176 "abcde/ab", 177 "abcde/ab/", 178 "abcde/abc", 179 "abcde/abc/", 180 "abcde/abcd", 181 "abcde/abcd/", 182 "abcde/abcde", 183 "abcde/abcde/", 184 "abcde/abcdef", 185 "abcde/abcdef/", 186 "abcde/abcdefg", 187 "abcde/abcdefg/", 188 "abcde/abcdefgh", 189 "abcde/abcdefgh/", 190 191 "abcdef/", 192 "abcdef//", 193 "abcdef/a", 194 "abcdef/a/", 195 "abcdef/ab", 196 "abcdef/ab/", 197 "abcdef/abc", 198 "abcdef/abc/", 199 "abcdef/abcd", 200 "abcdef/abcd/", 201 "abcdef/abcde", 202 "abcdef/abcde/", 203 "abcdef/abcdef", 204 "abcdef/abcdef/", 205 "abcdef/abcdefg", 206 "abcdef/abcdefg/", 207 "abcdef/abcdefgh", 208 "abcdef/abcdefgh/", 209 210 "abcdefg/", 211 "abcdefg//", 212 "abcdefg/a", 213 "abcdefg/a/", 214 "abcdefg/ab", 215 "abcdefg/ab/", 216 "abcdefg/abc", 217 "abcdefg/abc/", 218 "abcdefg/abcd", 219 "abcdefg/abcd/", 220 "abcdefg/abcde", 221 "abcdefg/abcde/", 222 "abcdefg/abcdef", 223 "abcdefg/abcdef/", 224 "abcdefg/abcdefg", 225 "abcdefg/abcdefg/", 226 "abcdefg/abcdefgh", 227 "abcdefg/abcdefgh/", 228 229 "abcdefgh/", 230 "abcdefgh//", 231 "abcdefgh/a", 232 "abcdefgh/a/", 233 "abcdefgh/ab", 234 "abcdefgh/ab/", 235 "abcdefgh/abc", 236 "abcdefgh/abc/", 237 "abcdefgh/abcd", 238 "abcdefgh/abcd/", 239 "abcdefgh/abcde", 240 "abcdefgh/abcde/", 241 "abcdefgh/abcdef", 242 "abcdefgh/abcdef/", 243 "abcdefgh/abcdefg", 244 "abcdefgh/abcdefg/", 245 "abcdefgh/abcdefgh", 246 "abcdefgh/abcdefgh/", 247 }; 248 249 dl_handle = dlopen(NULL, RTLD_LAZY); 250 strchr_fn = dlsym(dl_handle, "test_strchr"); 251 if (!strchr_fn) 252 strchr_fn = strchr; 253 254 for (a = 3; a < 3 + sizeof(long); ++a) { 255 /* Put char and a \0 before the buffer */ 256 buf[a-1] = '/'; 257 buf[a-2] = '0'; 258 buf[a-3] = 0xff; 259 for (t = 0; t < (sizeof(tab) / sizeof(tab[0])); ++t) { 260 int len = strlen(tab[t]) + 1; 261 memcpy(&buf[a], tab[t], len); 262 263 /* Put the char we are looking for after the \0 */ 264 buf[a + len] = '/'; 265 266 /* Check search for NUL at end of string */ 267 verify_strchr(buf + a, 0, t, a); 268 269 /* Then for the '/' in the strings */ 270 verify_strchr(buf + a, '/', t, a); 271 272 /* check zero extension of char arg */ 273 verify_strchr(buf + a, 0xffffff00 | '/', t, a); 274 275 /* Replace all the '/' with 0xff */ 276 while ((off = slow_strchr(buf + a, '/')) != NULL) 277 *off = 0xff; 278 279 buf[a + len] = 0xff; 280 281 /* Check we can search for 0xff as well as '/' */ 282 verify_strchr(buf + a, 0xff, t, a); 283 } 284 } 285 (void)dlclose(dl_handle); 286 } 287 288 ATF_TP_ADD_TCS(tp) 289 { 290 291 ATF_TP_ADD_TC(tp, strchr_basic); 292 293 return atf_no_error(); 294 } 295