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