summaryrefslogtreecommitdiff
path: root/usr/src/test/libc-tests/tests
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@fingolfin.org>2021-08-04 11:04:00 -0700
committerRobert Mustacchi <rm@fingolfin.org>2021-08-20 08:14:13 -0700
commitd6bf170859287b7b5b26419e266a7e6fdee7ff4d (patch)
treef91105a1d175639329cbacdaf0f981eeaca7d4be /usr/src/test/libc-tests/tests
parent4772ec9f4bc326d705888dcda49bcc395df74999 (diff)
downloadillumos-joyent-d6bf170859287b7b5b26419e266a7e6fdee7ff4d.tar.gz
13997 Want memrchr in libc
Reviewed by: Joshua M. Clulow <josh@sysmgr.org> Reviewed by: Andy Fiddaman <andy@omnios.org> Reviewed by: Toomas Soome <tsoome@me.com> Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/test/libc-tests/tests')
-rw-r--r--usr/src/test/libc-tests/tests/Makefile1
-rw-r--r--usr/src/test/libc-tests/tests/memchr.c294
2 files changed, 295 insertions, 0 deletions
diff --git a/usr/src/test/libc-tests/tests/Makefile b/usr/src/test/libc-tests/tests/Makefile
index c15aeba252..d818722d41 100644
--- a/usr/src/test/libc-tests/tests/Makefile
+++ b/usr/src/test/libc-tests/tests/Makefile
@@ -42,6 +42,7 @@ PROGS = \
endian \
env-7076 \
fnmatch \
+ memchr \
memset_s \
posix_memalign \
printf-9511 \
diff --git a/usr/src/test/libc-tests/tests/memchr.c b/usr/src/test/libc-tests/tests/memchr.c
new file mode 100644
index 0000000000..9ec3c6e0ef
--- /dev/null
+++ b/usr/src/test/libc-tests/tests/memchr.c
@@ -0,0 +1,294 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2021 Oxide Computer Company
+ */
+
+/*
+ * Various tests for memchr() and memrchr(). Note, this test assumes that the
+ * system is either ILP32 or LP64 with an 8-bit unsigned char due to the tests
+ * that are explicitly looking at making sure memchr() and memrchr() truncate
+ * correctly.
+ */
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <err.h>
+#include <stdlib.h>
+
+/*
+ * memchr_buf is a page sized buffer surrounded by two PROT_NONE pages which are
+ * meant to try and catch us walking over the edge of the buffer.
+ */
+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;
+ }
+
+ /*
+ * -190 is -0xbe, which when cast to an unsigned char will be 0x42.
+ */
+ 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);
+}