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