From 65bf1e3f6b2e49fb5c4de56ccc892b718da223cc Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 13 Dec 2024 19:34:10 -0800 Subject: [PATCH] Utils/FileLoading: Fix LoadFileImpl It is not an error that pread returns /less/ than what was requested. In fact it's very common for the Linux kernel to return less than the data requested from procfs. procfs keeps coming back to bite this function, previously it was fstat returning size of 0 which it hit. Now it only feeds data as much as it wants per loop. In particular /proc/self/maps would only read ~3k bytes on my system, but not be complete. To fully fix the issue, always make sure to keep reading until there is either an error OR zero is reached! --- FEXCore/Source/Utils/FileLoading.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/FEXCore/Source/Utils/FileLoading.cpp b/FEXCore/Source/Utils/FileLoading.cpp index e56ae36a89..a959107a64 100644 --- a/FEXCore/Source/Utils/FileLoading.cpp +++ b/FEXCore/Source/Utils/FileLoading.cpp @@ -31,24 +31,28 @@ static bool LoadFileImpl(T& Data, const fextl::string& Filepath, size_t FixedSiz FileSize = FixedSize; } + ssize_t CurrentOffset = 0; ssize_t Read = -1; bool LoadedFile {}; if (FileSize) { // File size is known upfront Data.resize(FileSize); - Read = pread(FD, &Data.at(0), FileSize, 0); + while ((Read = pread(FD, &Data.at(CurrentOffset), FileSize, 0)) > 0) { + CurrentOffset += Read; + } - LoadedFile = Read == FileSize; + LoadedFile = CurrentOffset == FileSize && Read != -1; } else { // The file is either empty or its size is unknown (e.g. procfs data). // Try reading in chunks instead - ssize_t CurrentOffset = 0; constexpr size_t READ_SIZE = 4096; Data.resize(READ_SIZE); - while ((Read = pread(FD, &Data.at(CurrentOffset), READ_SIZE, CurrentOffset)) == READ_SIZE) { + while ((Read = pread(FD, &Data.at(CurrentOffset), READ_SIZE, CurrentOffset)) > 0) { CurrentOffset += Read; - Data.resize(CurrentOffset + Read); + if ((CurrentOffset + READ_SIZE) > Data.size()) { + Data.resize(CurrentOffset + READ_SIZE); + } } if (Read == -1) {