Home | History | Annotate | Line # | Download | only in string
      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 (at) 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