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",