VirtualDiscFileSystem: reject ".." in .ppsspp-index.lst entries

fileName is taken verbatim from the index file (only a leading slash
is stripped) and then used essentially unsanitized to build a path
under basePath (GetLocalPath() is a plain string join, unlike
MetaFileSystem::RealPath which does collapse ".." for normal game file
access). A crafted index file - these virtual-disc folders are commonly
shared/downloaded as homebrew - could use a ".." component to make
PPSSPP probe or open arbitrary host files/directories outside the
intended folder just by loading it. Reuse the existing
HasParentDirComponent() helper (already used for the same purpose in
GameManager's zip extraction) to reject such entries.
This commit is contained in:
Henrik Rydgård
2026-08-11 08:57:15 +02:00
parent a82043eb9d
commit 93a8b0e501
@@ -27,6 +27,7 @@
#include "Core/FileSystems/ISOFileSystem.h"
#include "Core/HLE/sceKernel.h"
#include "Core/Reporting.h"
#include "Core/Util/PathUtil.h"
#include "Common/Data/Encoding/Utf8.h"
#include "Core/Config.h"
@@ -145,6 +146,16 @@ void VirtualDiscFileSystem::LoadFileListIndex() {
if (trunc != entry.fileName.npos && trunc != entry.fileName.size())
entry.fileName.resize(trunc + 1);
// This index file comes from the (often shared/downloaded) "virtual disc"
// folder itself, and fileName is used essentially unsanitized below (and
// throughout this class) to build a path under basePath. Without this check,
// a ".." component would let a crafted index file probe or open arbitrary
// host files/directories outside basePath.
if (HasParentDirComponent(entry.fileName)) {
ERROR_LOG(Log::FileSystem, "Ignoring index entry with parent directory reference: %s", entry.fileName.c_str());
continue;
}
entry.firstBlock = (u32)strtol(line.c_str(), NULL, 16);
if (entry.handler != NULL && entry.handler->IsValid()) {
HandlerFileHandle temp = entry.handler;