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.
This commit is contained in:
David committed 2026-10-22 14:57:02 +01:00
1 parent 8b3e39832a
commit 3db9e4ee05
1 file changed
+49
+49
View File
@@ -8,6 +8,20 @@
#include <cstdlib>
#include <string>
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;