fix(libc): switch update streams to reading in vfscanf

vfscanf, which vscanf and scanf also go through, read without switching
the stream to reading first. On Windows a vfscanf directly after fwrite
on an r+ stream returned bytes of the write buffer, as fscanf did before
a7e6e597d. It now calls SwitchToReading as fscanf does.
This commit is contained in:
dantdmdarealguy committed 2026-10-24 18:28:28 -05:00
1 parent f26434afa3
commit 4c2f9e3df7
2 files changed
+24

No files matched your search

+1
View File
@@ -653,6 +653,7 @@ extern FileStream* __stdinp_nid_postfix;
int APS5_VABI vfscanf_nid_postfix(FileStream* stream, const char* format, VaList* args) {
if (stream && !stream->IsOpen()) { errno = 9; return -1; }
auto* native = GetNativeStream(stream);
if (!stream->SwitchToReading()) return EOF;
#ifdef _WIN32
const int result = LibcDetail::ScanFileWindows_nid_no_patch(native, format, args);
#else
+23
View File
@@ -4,6 +4,7 @@
#include <array>
#include <barrier>
#include <cerrno>
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstring>
@@ -102,6 +103,23 @@ static void CheckExclusiveCppOpen(const std::string& base) {
}
}
static int APS5_VABI ScanList(FileStream* stream, const char* format, ...) {
#ifdef _WIN32
__builtin_sysv_va_list args;
__builtin_sysv_va_start(args, format);
#else
std::va_list args;
va_start(args, format);
#endif
const int result = vfscanf_nid_postfix(stream, format, reinterpret_cast<VaList*>(args));
#ifdef _WIN32
__builtin_sysv_va_end(args);
#else
va_end(args);
#endif
return result;
}
static std::string ReadWhole(const std::string& path) {
auto* stream = fopen_nid_postfix(path.c_str(), "rb");
Require(stream != nullptr);
@@ -158,6 +176,11 @@ static void CheckUpdateStreamReadsAfterWrites(const std::string& base) {
Require(fscanf_nid_postfix(stream, "%3s", buffer.data()) == 1, "fscanf after fwrite on an r+ stream");
Require(std::strcmp(buffer.data(), "234") == 0, "fscanf after fwrite on an r+ stream read other bytes");
});
CheckReadAfterWrite(path, "r+b", overwritten, [](FileStream* stream) {
std::array<char, 4> buffer{};
Require(ScanList(stream, "%3s", buffer.data()) == 1, "vfscanf after fwrite on an r+ stream");
Require(std::strcmp(buffer.data(), "234") == 0, "vfscanf after fwrite on an r+ stream read other bytes");
});
CheckReadAfterWrite(path, "w+b", "AB", [](FileStream* stream) {
std::array<char, 4> buffer{};
Require(fread_nid_postfix(buffer.data(), 1, buffer.size(), stream) == 0 && feof_nid_postfix(stream) != 0, "fread after fwrite on a w+ stream");