Add memrchr to the string library.
Change-Id: I8694c92f7169dc1c126fa165f07bfacd6810b6f4
diff --git a/sdk/include/string.h b/sdk/include/string.h
index 5261654..965a02b 100644
--- a/sdk/include/string.h
+++ b/sdk/include/string.h
@@ -11,6 +11,7 @@
void *__cheri_libcall memset(void *, int, size_t);
void *__cheri_libcall memmove(void *dest, const void *src, size_t n);
void *__cheri_libcall memchr(const void *, int, size_t);
+void *__cheri_libcall memrchr(const void *, int, size_t);
size_t __cheri_libcall strlen(const char *str);
int __cheri_libcall strncmp(const char *s1, const char *s2, size_t n);
char *__cheri_libcall strncpy(char *dest, const char *src, size_t n);
diff --git a/sdk/lib/string/memrchr.c b/sdk/lib/string/memrchr.c
new file mode 100644
index 0000000..bf51298
--- /dev/null
+++ b/sdk/lib/string/memrchr.c
@@ -0,0 +1,24 @@
+// Copyright SCI Semiconductor and CHERIoT Contributors.
+// SPDX-License-Identifier: MIT
+
+#include <string.h>
+
+void *__cheri_libcall memrchr(const void *voidString,
+ int intChar,
+ size_t n)
+{
+ const unsigned char c = (unsigned char)intChar;
+ const unsigned char *s = (const unsigned char *)voidString;
+
+ s += n;
+ for (size_t i = n; i > 0; --i)
+ {
+ --s;
+ if (*s == c)
+ {
+ return (void *)s;
+ }
+ }
+
+ return NULL;
+}
diff --git a/sdk/lib/string/xmake.lua b/sdk/lib/string/xmake.lua
index ded4a00..002f5e3 100644
--- a/sdk/lib/string/xmake.lua
+++ b/sdk/lib/string/xmake.lua
@@ -1,3 +1,3 @@
library("string")
set_default(false)
- add_files("strcmp.c", "strlen.c", "strncpy.c", "strstr.cc", "strchr.c", "strlcpy.c", "memchr.c")
+ add_files("strcmp.c", "strlen.c", "strncpy.c", "strstr.cc", "strchr.c", "strlcpy.c", "memchr.c", "memrchr.c")
diff --git a/tests/misc-test.cc b/tests/misc-test.cc
index 9c54c71..28352b1 100644
--- a/tests/misc-test.cc
+++ b/tests/misc-test.cc
@@ -90,6 +90,43 @@
}
/**
+ * Test memrchr.
+ *
+ * This test checks the following:
+ *
+ * - memrchr finds the first occurrence of the character when it is present
+ * (test for different values, particularly the first and the last one).
+ * - memrchr returns NULL when the string does not contain the character (test
+ * for non-NULL terminated string).
+ * - memrchr does not stop at \0 characters.
+ * - memrchr returns NULL for 0-size pointers.
+ */
+void check_memrchr()
+{
+ debug_log("Test memrchr.");
+
+ char string[] = {'C', 'H', 'E', 'R', 'R', 'I', 'O', 'T'};
+
+ TEST(memchr(string, 'C', sizeof(string)) == &string[0],
+ "memrchr must return the first occurence of the character.");
+ TEST(memrchr(string, 'R', sizeof(string)) == &string[4],
+ "memrchr must return the first occurence of the character.");
+ TEST(memrchr(string, 'T', sizeof(string)) == &string[7],
+ "memrchr must return the first occurence of the character.");
+ TEST(memrchr(string, 'X', sizeof(string)) == NULL,
+ "memrchr must return NULL when a character is not present.");
+
+ char stringWithNull[] = {'F', 'U', '\0', 'B', 'A', 'R', '\0'};
+
+ TEST(memrchr(stringWithNull, 'F', sizeof(stringWithNull)) ==
+ &stringWithNull[0],
+ "memrchr must not stop at NULL characters.");
+
+ TEST(memrchr(stringWithNull, 'Y', 0) == NULL,
+ "memrchr must return NULL for zero-size pointers.");
+}
+
+/**
* Test pointer utilities.
*
* Not comprehensive, would benefit from being expanded at some point.
@@ -137,6 +174,7 @@
{
check_timeouts();
check_memchr();
+ check_memrchr();
check_pointer_utilities();
debug_log("Testing shared objects.");
check_shared_object("exampleK",