#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <err.h>
#include <stdlib.h>
static uint8_t *memchr_buf;
static size_t memchr_buflen;
static void
memchr_setup(void)
{
size_t pgsz = getpagesize();
void *addr;
if (pgsz <= 0) {
err(EXIT_FAILURE, "failed to get system page size");
}
addr = mmap(NULL, 3 * pgsz, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (addr == MAP_FAILED) {
err(EXIT_FAILURE, "failed to mmap %zu bytes", 3 * pgsz);
}
memchr_buf = (uint8_t *)addr + pgsz;
memchr_buflen = pgsz;
if (mprotect(addr, pgsz, PROT_NONE) != 0) {
err(EXIT_FAILURE, "failed to protect leading PROT_NONE guard "
"at %p", addr);
}
addr = (uint8_t *)addr + 2 * pgsz;
if (mprotect(addr, pgsz, PROT_NONE) != 0) {
err(EXIT_FAILURE, "failed to protect trailing PROT_NONE guard "
"at %p", addr);
}
}
static boolean_t
memchr_basic(void)
{
boolean_t ret = B_TRUE;
const void *targ;
const void *found;
(void) memset(memchr_buf, 0, memchr_buflen);
memchr_buf[0] = 'r';
if ((found = memchr(memchr_buf, 'r', memchr_buflen)) != memchr_buf) {
warnx("TEST FAILED: memchr failed to find 'r' (1), found %p, "
"expected %p", found, memchr_buf);
ret = B_FALSE;
}
if ((found = memrchr(memchr_buf, 'r', memchr_buflen)) != memchr_buf) {
warnx("TEST FAILED: memrchr failed to find 'r' (1), found %p, "
"expected %p", found, memchr_buf);
ret = B_FALSE;
}
memchr_buf[memchr_buflen - 1] = 'r';
targ = &memchr_buf[memchr_buflen - 1];
if ((found = memchr(memchr_buf, 'r', memchr_buflen)) != memchr_buf) {
warnx("TEST FAILED: memchr failed to find 'r' (2), found %p, "
"expected %p", found, memchr_buf);
ret = B_FALSE;
}
if ((found = memrchr(memchr_buf, 'r', memchr_buflen)) != targ) {
warnx("TEST FAILED: memrchr failed to find 'r' (2), found %p, "
"expected %p", found, targ);
warnx("TEST FAILED: memchr failed to find 'r'");
ret = B_FALSE;
}
memchr_buf[0] = 0;
if ((found = memchr(memchr_buf, 'r', memchr_buflen)) != targ) {
warnx("TEST FAILED: memchr failed to find 'r' (3), found %p, "
"expected %p", found, targ);
ret = B_FALSE;
}
if ((found = memrchr(memchr_buf, 'r', memchr_buflen)) != targ) {
warnx("TEST FAILED: memrchr failed to find 'r' (3), found %p, "
"expected %p", found, targ);
ret = B_FALSE;
}
if (ret) {
(void) printf("TEST PASSED: basic memchr() and memrchr()\n");
}
return (ret);
}
static boolean_t
memchr_notfound(void)
{
boolean_t ret = B_TRUE;
const void *found;
(void) memset(memchr_buf, 0x23, memchr_buflen);
if ((found = memchr(memchr_buf, 0, memchr_buflen)) != NULL) {
warnx("TEST FAILED: memchr unexpectedly found value (1), "
"found %p, expected %p", found, NULL);
ret = B_FALSE;
}
if (memrchr(memchr_buf, 0, memchr_buflen) != NULL) {
warnx("TEST FAILED: memrchr unexpectedly found value (1), "
"found %p, expected %p", found, NULL);
ret = B_FALSE;
}
if (memchr(memchr_buf, 0x24, memchr_buflen) != NULL) {
warnx("TEST FAILED: memchr unexpectedly found value (2), "
"found %p, expected %p", found, NULL);
ret = B_FALSE;
}
if (memrchr(memchr_buf, 0x24, memchr_buflen) != NULL) {
warnx("TEST FAILED: memrchr unexpectedly found value (2), "
"found %p, expected %p", found, NULL);
ret = B_FALSE;
}
memchr_buf[1] = 0x24;
if (memchr(memchr_buf, 0x24, 1) != NULL) {
warnx("TEST FAILED: memchr unexpectedly found value (3), "
"found %p, expected %p", found, NULL);
ret = B_FALSE;
}
if (memrchr(memchr_buf, 0x24, 1) != NULL) {
warnx("TEST FAILED: memrchr unexpectedly found value (3), "
"found %p, expected %p", found, NULL);
ret = B_FALSE;
}
memchr_buf[1] = 0x24;
if (memchr(memchr_buf + 1, 0x23, 1) != NULL) {
warnx("TEST FAILED: memchr unexpectedly found value (4), "
"found %p, expected %p", found, NULL);
ret = B_FALSE;
}
if (memrchr(memchr_buf + 1, 0x23, 1) != NULL) {
warnx("TEST FAILED: memrchr unexpectedly found value (4), "
"found %p, expected %p", found, NULL);
ret = B_FALSE;
}
if (ret) {
(void) printf("TEST PASSED: memchr() and memrchr() on "
"missing values\n");
}
return (ret);
}
static boolean_t
memchr_truncation(void)
{
boolean_t ret = B_TRUE;
const void *found;
const void *targ;
(void) memset(memchr_buf, 0x42, memchr_buflen);
if ((found = memchr(memchr_buf, 0x42, memchr_buflen)) != memchr_buf) {
warnx("TEST FAILED: memchr failed to find 0x42, found %p, "
"expected %p", found, memchr_buf);
ret = B_FALSE;
}
targ = &memchr_buf[memchr_buflen - 1];
if ((found = memrchr(memchr_buf, 0x42, memchr_buflen)) != targ) {
warnx("TEST FAILED: memrchr failed to find 0x42, found %p, "
"expected %p", found, targ);
ret = B_FALSE;
}
if ((found = memchr(memchr_buf, 0x430042, memchr_buflen)) !=
memchr_buf) {
warnx("TEST FAILED: memchr failed to find 0x42 with 0x430042, "
"found %p, expected %p", found, memchr_buf);
ret = B_FALSE;
}
if ((found = memrchr(memchr_buf, 0x430042, memchr_buflen)) != targ) {
warnx("TEST FAILED: memrchr failed to find 0x42 with 0x430042, "
"found %p, expected %p", found, targ);
ret = B_FALSE;
}
if ((found = memchr(memchr_buf, -190, memchr_buflen)) != memchr_buf) {
warnx("TEST FAILED: memchr failed to find 0x42 with -190, "
"found %p, expected %p", found, memchr_buf);
ret = B_FALSE;
}
if ((found = memrchr(memchr_buf, -190, memchr_buflen)) != targ) {
warnx("TEST FAILED: memrchr failed to find 0x42 with -190, "
"found %p, expected %p", found, targ);
ret = B_FALSE;
}
if ((found = memchr(memchr_buf, -190, memchr_buflen)) != memchr_buf) {
warnx("TEST FAILED: memchr failed to find 0x42 with -190, "
"found %p, expected %p", found, memchr_buf);
ret = B_FALSE;
}
if ((found = memrchr(memchr_buf, -190, memchr_buflen)) != targ) {
warnx("TEST FAILED: memrchr failed to find 0x42 with -190, "
"found %p, expected %p", found, targ);
ret = B_FALSE;
}
if ((found = memchr(memchr_buf, 0x42424200, memchr_buflen)) != NULL) {
warnx("TEST FAILED: memchr somehow found 0x42 with "
"0x42424200, found %p, expected NULL", found);
ret = B_FALSE;
}
if ((found = memrchr(memchr_buf, 0x42424200, memchr_buflen)) != NULL) {
warnx("TEST FAILED: memrchr somehow found 0x42 with "
"0x42424200, found %p, expected NULL", found);
ret = B_FALSE;
}
if (ret) {
(void) printf("TEST PASSED: truncated values\n");
}
return (B_TRUE);
}
int
main(void)
{
int ret = EXIT_SUCCESS;
memchr_setup();
if (!memchr_basic())
ret = EXIT_FAILURE;
if (!memchr_notfound())
ret = EXIT_FAILURE;
if (!memchr_truncation())
ret = EXIT_FAILURE;
if (ret == EXIT_SUCCESS) {
(void) printf("All tests passed successfully\n");
}
return (ret);
}