From 3cb434715afebef4a4e7260b9ed062e06447e4d3 Mon Sep 17 00:00:00 2001 From: QRMOE Date: Mon, 12 Oct 2026 19:00:50 +0200 Subject: [PATCH 1/2] fix(libc): clear exhausted strtok continuation state --- core/libs/prx/libc/src/StringExtensions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/libs/prx/libc/src/StringExtensions.cpp b/core/libs/prx/libc/src/StringExtensions.cpp index 8ea34819c..f1f4eb975 100644 --- a/core/libs/prx/libc/src/StringExtensions.cpp +++ b/core/libs/prx/libc/src/StringExtensions.cpp @@ -127,11 +127,12 @@ char* APS5_VABI strtok_r_nid_postfix(char* text, const char* delimiters, char** if (text == nullptr) return nullptr; text += std::strspn(text, delimiters); if (*text == '\0') { - *state = text; + *state = nullptr; return nullptr; } char* end = text + std::strcspn(text, delimiters); if (*end != '\0') *end++ = '\0'; + else end = nullptr; *state = end; return text; } From 0950b198543f159b66af9e88213b8a81c99b3bff Mon Sep 17 00:00:00 2001 From: QRMOE Date: Mon, 12 Oct 2026 19:01:27 +0200 Subject: [PATCH 2/2] test(libc): cover exhausted tokenizer state --- core/libs/tests/GuestStrings.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/core/libs/tests/GuestStrings.cpp b/core/libs/tests/GuestStrings.cpp index ec0b4f01d..1c0e27fd5 100644 --- a/core/libs/tests/GuestStrings.cpp +++ b/core/libs/tests/GuestStrings.cpp @@ -293,11 +293,32 @@ int main() { char* firstState = nullptr; char* secondState = nullptr; Require(std::strcmp(strtok_r_nid_postfix(first, ",", &firstState), "a") == 0); + Require(firstState == first + 3); Require(std::strcmp(strtok_r_nid_postfix(second, ":", &secondState), "x") == 0); + Require(secondState == second + 2); Require(std::strcmp(strtok_r_nid_postfix(nullptr, ",", &firstState), "b") == 0); + Require(firstState == first + 6); Require(strtok_r_nid_postfix(nullptr, ",", &firstState) == nullptr); + if (firstState != nullptr) std::fputs("strtok_r retained the state after exhausting delimiters\n", stderr); + Require(firstState == nullptr); Require(strtok_r_nid_postfix(nullptr, ",", &firstState) == nullptr); Require(std::strcmp(strtok_r_nid_postfix(nullptr, "", &secondState), "y") == 0); + Require(secondState == nullptr); + char tokenEnd[8] = "last"; + char* finishedState = first; + *__error_nid_postfix() = 77; + Require(strtok_r_nid_postfix(tokenEnd, ",", &finishedState) == tokenEnd && finishedState == nullptr); + tokenEnd[4] = 'x'; + tokenEnd[5] = '\0'; + Require(strtok_r_nid_postfix(nullptr, ",", &finishedState) == nullptr && finishedState == nullptr); + for (const char* input : {"", ",", ",,,"}) { + char noTokens[8]; + std::strcpy(noTokens, input); + finishedState = first; + Require(strtok_r_nid_postfix(noTokens, ",", &finishedState) == nullptr && finishedState == nullptr); + Require(strtok_r_nid_postfix(nullptr, ",", &finishedState) == nullptr); + } + Require(*__error_nid_postfix() == 77); char hostTokens[] = "host:next"; Require(std::strcmp(std::strtok(hostTokens, ":"), "host") == 0); char guestTokens[] = ",one,,two:three";