RamCachingFileLoader: don't round a mid-file short read up to a full block

blocksActuallyRead rounded bytesRead up to the next whole block
unconditionally, intending to handle the legitimate case where the
very last block of the file is naturally shorter than BLOCK_SIZE
(cache_ is deliberately over-allocated for that). But it applied the
same rounding to any short read, including a genuine failure or a
dropped connection mid-file (this loader can sit on top of the whole
Remote ISO chain via CachingFileLoader/HTTPFileLoader when "Cache full
ISO in RAM" is enabled) - marking a block as fully cached when only a
few of its bytes were actually written. Since cache_ is malloc'd (not
zeroed), every later read of that block would serve uninitialized heap
memory as if it were real file data.

Only round up when the short read's end position exactly matches the
true end of the file.
This commit is contained in:
Henrik Rydgård
2026-08-11 08:54:16 +02:00
parent f7f92c5db7
commit 67f2bf57cb
+10 -1
View File
@@ -189,7 +189,16 @@ void RamCachingFileLoader::SaveIntoCache(s64 pos, size_t bytes, Flags flags) {
size_t bytesRead = backend_->ReadAt(cacheFilePos, blocksToRead << BLOCK_SHIFT, &cache_[cacheFilePos], flags);
// In case there was an error, let's not mark blocks that failed to read as read.
u32 blocksActuallyRead = (u32)((bytesRead + BLOCK_SIZE - 1) >> BLOCK_SHIFT);
// Round up only for a genuine short read exactly at the true end of the file -
// cache_ is deliberately over-allocated to a full BLOCK_SIZE for the last block,
// so its unwritten tail past filesize_ is never read back. Any other short read
// (e.g. a dropped Remote ISO connection mid-file) must not be rounded up, or the
// unwritten (uninitialized, since cache_ is malloc'd) rest of that block would be
// served as if it were real file data.
u32 blocksActuallyRead = (u32)(bytesRead >> BLOCK_SHIFT);
if ((bytesRead & (BLOCK_SIZE - 1)) != 0 && cacheFilePos + (s64)bytesRead == filesize_) {
++blocksActuallyRead;
}
{
std::lock_guard<std::mutex> guard(blocksMutex_);