xref: /illumos-gate/usr/src/test/libc-tests/tests/memchr.c (revision e8d3efa1c56e5f2b5368600a2baeb7b1d54a07f8)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2021 Oxide Computer Company
14  */
15 
16 /*
17  * Various tests for memchr() and memrchr(). Note, this test assumes that the
18  * system is either ILP32 or LP64 with an 8-bit unsigned char due to the tests
19  * that are explicitly looking at making sure memchr() and memrchr() truncate
20  * correctly.
21  */
22 
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/mman.h>
26 #include <err.h>
27 #include <stdlib.h>
28 
29 /*
30  * memchr_buf is a page sized buffer surrounded by two PROT_NONE pages which are
31  * meant to try and catch us walking over the edge of the buffer.
32  */
33 static uint8_t *memchr_buf;
34 static size_t memchr_buflen;
35 
36 static void
37 memchr_setup(void)
38 {
39 	size_t pgsz;
40 	int pg = getpagesize();
41 	void *addr;
42 
43 	if (pg <= 0) {
44 		err(EXIT_FAILURE, "failed to get system page size");
45 	} else {
46 		pgsz = pg;
47 	}
48 
49 	addr = mmap(NULL, 3 * pgsz, PROT_READ | PROT_WRITE,
50 	    MAP_PRIVATE | MAP_ANON, -1, 0);
51 	if (addr == MAP_FAILED) {
52 		err(EXIT_FAILURE, "failed to mmap %zu bytes", 3 * pgsz);
53 	}
54 
55 	memchr_buf = (uint8_t *)addr + pgsz;
56 	memchr_buflen = pgsz;
57 
58 	if (mprotect(addr, pgsz, PROT_NONE) != 0) {
59 		err(EXIT_FAILURE, "failed to protect leading PROT_NONE guard "
60 		    "at %p", addr);
61 	}
62 
63 	addr = (uint8_t *)addr + 2 * pgsz;
64 	if (mprotect(addr, pgsz, PROT_NONE) != 0) {
65 		err(EXIT_FAILURE, "failed to protect trailing PROT_NONE guard "
66 		    "at %p", addr);
67 	}
68 }
69 
70 static boolean_t
71 memchr_basic(void)
72 {
73 	boolean_t ret = B_TRUE;
74 	const void *targ;
75 	const void *found;
76 
77 	(void) memset(memchr_buf, 0, memchr_buflen);
78 	memchr_buf[0] = 'r';
79 
80 	if ((found = memchr(memchr_buf, 'r', memchr_buflen)) != memchr_buf) {
81 		warnx("TEST FAILED: memchr failed to find 'r' (1), found %p, "
82 		    "expected %p", found, memchr_buf);
83 		ret = B_FALSE;
84 	}
85 
86 	if ((found = memrchr(memchr_buf, 'r', memchr_buflen)) != memchr_buf) {
87 		warnx("TEST FAILED: memrchr failed to find 'r' (1), found %p, "
88 		    "expected %p", found, memchr_buf);
89 		ret = B_FALSE;
90 	}
91 
92 	memchr_buf[memchr_buflen - 1] = 'r';
93 	targ = &memchr_buf[memchr_buflen - 1];
94 
95 	if ((found = memchr(memchr_buf, 'r', memchr_buflen)) != memchr_buf) {
96 		warnx("TEST FAILED: memchr failed to find 'r' (2), found %p, "
97 		    "expected %p", found, memchr_buf);
98 		ret = B_FALSE;
99 	}
100 
101 	if ((found = memrchr(memchr_buf, 'r', memchr_buflen)) != targ) {
102 		warnx("TEST FAILED: memrchr failed to find 'r' (2), found %p, "
103 		    "expected %p", found, targ);
104 		warnx("TEST FAILED: memchr failed to find 'r'");
105 		ret = B_FALSE;
106 	}
107 
108 	memchr_buf[0] = 0;
109 
110 	if ((found = memchr(memchr_buf, 'r', memchr_buflen)) != targ) {
111 		warnx("TEST FAILED: memchr failed to find 'r' (3), found %p, "
112 		    "expected %p", found, targ);
113 		ret = B_FALSE;
114 	}
115 
116 	if ((found = memrchr(memchr_buf, 'r', memchr_buflen)) != targ) {
117 		warnx("TEST FAILED: memrchr failed to find 'r' (3), found %p, "
118 		    "expected %p", found, targ);
119 		ret = B_FALSE;
120 	}
121 
122 	if (ret) {
123 		(void) printf("TEST PASSED: basic memchr() and memrchr()\n");
124 	}
125 	return (ret);
126 }
127 
128 static boolean_t
129 memchr_notfound(void)
130 {
131 	boolean_t ret = B_TRUE;
132 	const void *found;
133 
134 	(void) memset(memchr_buf, 0x23, memchr_buflen);
135 
136 	if ((found = memchr(memchr_buf, 0, memchr_buflen)) != NULL) {
137 		warnx("TEST FAILED: memchr unexpectedly found value (1), "
138 		    "found %p, expected %p", found, NULL);
139 		ret = B_FALSE;
140 	}
141 
142 	if (memrchr(memchr_buf, 0, memchr_buflen) != NULL) {
143 		warnx("TEST FAILED: memrchr unexpectedly found value (1), "
144 		    "found %p, expected %p", found, NULL);
145 		ret = B_FALSE;
146 	}
147 
148 	if (memchr(memchr_buf, 0x24, memchr_buflen) != NULL) {
149 		warnx("TEST FAILED: memchr unexpectedly found value (2), "
150 		    "found %p, expected %p", found, NULL);
151 		ret = B_FALSE;
152 	}
153 
154 	if (memrchr(memchr_buf, 0x24, memchr_buflen) != NULL) {
155 		warnx("TEST FAILED: memrchr unexpectedly found value (2), "
156 		    "found %p, expected %p", found, NULL);
157 		ret = B_FALSE;
158 	}
159 
160 	memchr_buf[1] = 0x24;
161 
162 	if (memchr(memchr_buf, 0x24, 1) != NULL) {
163 		warnx("TEST FAILED: memchr unexpectedly found value (3), "
164 		    "found %p, expected %p", found, NULL);
165 		ret = B_FALSE;
166 	}
167 
168 	if (memrchr(memchr_buf, 0x24, 1) != NULL) {
169 		warnx("TEST FAILED: memrchr unexpectedly found value (3), "
170 		    "found %p, expected %p", found, NULL);
171 		ret = B_FALSE;
172 	}
173 
174 	memchr_buf[1] = 0x24;
175 
176 	if (memchr(memchr_buf + 1, 0x23, 1) != NULL) {
177 		warnx("TEST FAILED: memchr unexpectedly found value (4), "
178 		    "found %p, expected %p", found, NULL);
179 		ret = B_FALSE;
180 	}
181 
182 	if (memrchr(memchr_buf + 1, 0x23, 1) != NULL) {
183 		warnx("TEST FAILED: memrchr unexpectedly found value (4), "
184 		    "found %p, expected %p", found, NULL);
185 		ret = B_FALSE;
186 	}
187 
188 	if (ret) {
189 		(void) printf("TEST PASSED: memchr() and memrchr() on "
190 		    "missing values\n");
191 	}
192 
193 	return (ret);
194 }
195 
196 static boolean_t
197 memchr_truncation(void)
198 {
199 	boolean_t ret = B_TRUE;
200 	const void *found;
201 	const void *targ;
202 
203 	(void) memset(memchr_buf, 0x42, memchr_buflen);
204 
205 	if ((found = memchr(memchr_buf, 0x42, memchr_buflen)) != memchr_buf) {
206 		warnx("TEST FAILED: memchr failed to find 0x42, found %p, "
207 		    "expected %p", found, memchr_buf);
208 		ret = B_FALSE;
209 	}
210 
211 	targ = &memchr_buf[memchr_buflen - 1];
212 
213 	if ((found = memrchr(memchr_buf, 0x42, memchr_buflen)) != targ) {
214 		warnx("TEST FAILED: memrchr failed to find 0x42, found %p, "
215 		    "expected %p", found, targ);
216 		ret = B_FALSE;
217 	}
218 
219 	if ((found = memchr(memchr_buf, 0x430042, memchr_buflen)) !=
220 	    memchr_buf) {
221 		warnx("TEST FAILED: memchr failed to find 0x42 with 0x430042, "
222 		    "found %p, expected %p", found, memchr_buf);
223 		ret = B_FALSE;
224 	}
225 
226 	if ((found = memrchr(memchr_buf, 0x430042, memchr_buflen)) != targ) {
227 		warnx("TEST FAILED: memrchr failed to find 0x42 with 0x430042, "
228 		    "found %p, expected %p", found, targ);
229 		ret = B_FALSE;
230 	}
231 
232 	/*
233 	 * -190 is -0xbe, which when cast to an unsigned char will be 0x42.
234 	 */
235 	if ((found = memchr(memchr_buf, -190, memchr_buflen)) != memchr_buf) {
236 		warnx("TEST FAILED: memchr failed to find 0x42 with -190, "
237 		    "found %p, expected %p", found, memchr_buf);
238 		ret = B_FALSE;
239 	}
240 
241 	if ((found = memrchr(memchr_buf, -190, memchr_buflen)) != targ) {
242 		warnx("TEST FAILED: memrchr failed to find 0x42 with -190, "
243 		    "found %p, expected %p", found, targ);
244 		ret = B_FALSE;
245 	}
246 
247 	if ((found = memchr(memchr_buf, -190, memchr_buflen)) != memchr_buf) {
248 		warnx("TEST FAILED: memchr failed to find 0x42 with -190, "
249 		    "found %p, expected %p", found, memchr_buf);
250 		ret = B_FALSE;
251 	}
252 
253 	if ((found = memrchr(memchr_buf, -190, memchr_buflen)) != targ) {
254 		warnx("TEST FAILED: memrchr failed to find 0x42 with -190, "
255 		    "found %p, expected %p", found, targ);
256 		ret = B_FALSE;
257 	}
258 
259 	if ((found = memchr(memchr_buf, 0x42424200, memchr_buflen)) != NULL) {
260 		warnx("TEST FAILED: memchr somehow found 0x42 with "
261 		    "0x42424200, found %p, expected NULL", found);
262 		ret = B_FALSE;
263 	}
264 
265 	if ((found = memrchr(memchr_buf, 0x42424200, memchr_buflen)) != NULL) {
266 		warnx("TEST FAILED: memrchr somehow found 0x42 with "
267 		    "0x42424200, found %p, expected NULL", found);
268 		ret = B_FALSE;
269 	}
270 
271 	if (ret) {
272 		(void) printf("TEST PASSED: truncated values\n");
273 	}
274 
275 	return (B_TRUE);
276 }
277 
278 int
279 main(void)
280 {
281 	int ret = EXIT_SUCCESS;
282 
283 	memchr_setup();
284 
285 	if (!memchr_basic())
286 		ret = EXIT_FAILURE;
287 	if (!memchr_notfound())
288 		ret = EXIT_FAILURE;
289 	if (!memchr_truncation())
290 		ret = EXIT_FAILURE;
291 
292 	if (ret == EXIT_SUCCESS) {
293 		(void) printf("All tests passed successfully\n");
294 	}
295 
296 	return (ret);
297 }
298