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