From 3db9e4ee0577f4184554942a1482e43e4c8e924f Mon Sep 17 00:00:00 2001 From: David Date: Thu, 22 Oct 2026 14:57:02 +0100 Subject: [PATCH] test(libc): cover the standard string exports guest_strings checked the bounds-checked and BSD string functions but not the plain C ones. It now checks strcmp, strncmp and strcoll by sign, strlen, strcpy and strcat return values, strncpy zero padding and its unterminated truncation, strstr with an empty needle, strspn, bcmp and bzero. --- core/libs/tests/GuestStrings.cpp | 49 ++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/core/libs/tests/GuestStrings.cpp b/core/libs/tests/GuestStrings.cpp index ef2f2f0a69..34eeb0aa03 100644 --- a/core/libs/tests/GuestStrings.cpp +++ b/core/libs/tests/GuestStrings.cpp @@ -8,6 +8,20 @@ #include #include +extern "C" { +void APS5_VABI bzero_nid_postfix(void* destination, size_t count); +int APS5_VABI bcmp_nid_postfix(const void* s1, const void* s2, size_t n); +int APS5_VABI strcmp_nid_postfix(const char* s1, const char* s2); +int APS5_VABI strncmp_nid_postfix(const char* s1, const char* s2, size_t n); +int APS5_VABI strcoll_nid_postfix(const char* s1, const char* s2); +size_t APS5_VABI strlen_nid_postfix(const char* s); +char* APS5_VABI strcpy_nid_postfix(char* dest, const char* src); +char* APS5_VABI strncpy_nid_postfix(char* dest, const char* src, size_t count); +char* APS5_VABI strcat_nid_postfix(char* dest, const char* src); +char* APS5_VABI strstr_nid_postfix(const char* haystack, const char* needle); +size_t APS5_VABI strspn_nid_postfix(const char* s, const char* accept); +} + extern "C" { void APS5_VABI bcopy_nid_postfix(const void*, void*, std::size_t); char* APS5_VABI basename_nid_postfix(const char*); @@ -82,6 +96,40 @@ static bool CheckMemcpyOverlap() { return correct; } +static int Sign(int value) { + return value < 0 ? -1 : value > 0 ? 1 : 0; +} + +static void CheckStandardStrings() { + Require(strcmp_nid_postfix("abc", "abc") == 0 && Sign(strcmp_nid_postfix("abc", "abd")) == -1 && Sign(strcmp_nid_postfix("abc", "ab")) == 1); + Require(Sign(strcmp_nid_postfix("\x80", "\x7f")) == 1); + Require(strncmp_nid_postfix("abcX", "abcY", 3) == 0 && Sign(strncmp_nid_postfix("abcX", "abcY", 4)) == -1 && strncmp_nid_postfix("a", "b", 0) == 0); + Require(strcoll_nid_postfix("same", "same") == 0 && Sign(strcoll_nid_postfix("B", "a")) == -1); + Require(strlen_nid_postfix("") == 0 && strlen_nid_postfix("seven 7") == 7); + + char buffer[16]; + std::memset(buffer, 'x', sizeof(buffer)); + Require(strcpy_nid_postfix(buffer, "ab") == buffer && std::memcmp(buffer, "ab\0x", 4) == 0); + Require(strcat_nid_postfix(buffer, "cd") == buffer && std::strcmp(buffer, "abcd") == 0); + + std::memset(buffer, 'x', sizeof(buffer)); + Require(strncpy_nid_postfix(buffer, "ab", 5) == buffer && std::memcmp(buffer, "ab\0\0\0x", 6) == 0); + std::memset(buffer, 'x', sizeof(buffer)); + Require(strncpy_nid_postfix(buffer, "abcdef", 3) == buffer && std::memcmp(buffer, "abcx", 4) == 0); + + const char* text = "needle in a haystack"; + Require(strstr_nid_postfix(text, "hay") == text + 12 && strstr_nid_postfix(text, "") == text && strstr_nid_postfix(text, "hey") == nullptr); + Require(strspn_nid_postfix("aabbc", "ab") == 4 && strspn_nid_postfix("xyz", "ab") == 0 && strspn_nid_postfix("ab", "") == 0); + + unsigned char bytes[6] = {1, 2, 3, 4, 5, 6}; + const unsigned char same[6] = {1, 2, 3, 4, 5, 6}; + Require(bcmp_nid_postfix(bytes, same, 6) == 0 && bcmp_nid_postfix(bytes, "zz", 0) == 0); + bytes[5] = 9; + Require(bcmp_nid_postfix(bytes, same, 6) != 0 && bcmp_nid_postfix(bytes, same, 5) == 0); + bzero_nid_postfix(bytes + 1, 4); + Require(bytes[0] == 1 && bytes[1] == 0 && bytes[4] == 0 && bytes[5] == 9); +} + static void CheckSecureCopySizeLimits() { using Copy = int (APS5_VABI*)(void*, std::size_t, const void*, std::size_t); constexpr std::size_t RsizeMax = SIZE_MAX >> 1; @@ -327,6 +375,7 @@ static void CheckCharacterConversionInSearches() { } int main() { + CheckStandardStrings(); CheckStrtonum(); CheckBcopy(); if (!CheckDirnameLengths()) return 1;