mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-07 21:23:29 +02:00
ISOFileSystem: Clamp file sizes to what the image actually contains
The size in an ISO directory record is untrusted, and callers allocate host
buffers from it - GetISOGameID and ReadFileToString did so directly until the
previous commit, and ReadFile clamps reads to the claimed size rather than to
the image.
We've warned about out-of-range extents since c766536914, but deliberately kept
the file, and rounded down so the warning wouldn't fire on borderline images.
Keep that behavior and just clamp the recorded size to the bytes that really
exist. For a well-formed file the extent always fits within its sectors, so this
never triggers; for a truncated one the game keeps booting instead of losing the
file entirely.
This commit is contained in:
@@ -302,6 +302,20 @@ void ISOFileSystem::ReadDirectory(TreeEntry *root) const {
|
||||
ERROR_LOG(Log::FileSystem, "File '%s' starts or ends outside ISO. firstDataSector: %d len: %d", entry->BuildPath().c_str(), (int)dir.firstDataSector, (int)dir.dataLength);
|
||||
}
|
||||
|
||||
// The directory record is untrusted, and callers size host buffers from entry->size, so
|
||||
// don't let it claim more data than the image actually contains. We clamp rather than
|
||||
// drop the entry - truncated ISOs are common and used to work with just the warning
|
||||
// above, and dropping EBOOT.BIN would turn that into an unbootable game. For a sane
|
||||
// file this is a no-op, since the extent always fits in its sectors.
|
||||
if (isFile) {
|
||||
const u64 numBlocks = blockDevice->GetNumBlocks();
|
||||
const u64 firstSector = dir.firstDataSector;
|
||||
const s64 availableBytes = firstSector >= numBlocks ? 0 : (s64)((numBlocks - firstSector) * (u64)sectorSize);
|
||||
if (entry->size > availableBytes) {
|
||||
entry->size = availableBytes;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry->isDirectory && !relative) {
|
||||
if (entry->startsector == root->startsector) {
|
||||
blockDevice->NotifyReadError();
|
||||
|
||||
Reference in New Issue
Block a user