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