From 93a8b0e5013eafebbd6aeb2c65f4fcd172e8e2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 11 Aug 2026 01:29:52 +0200 Subject: [PATCH] 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. --- Core/FileSystems/VirtualDiscFileSystem.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Core/FileSystems/VirtualDiscFileSystem.cpp b/Core/FileSystems/VirtualDiscFileSystem.cpp index cac8793471..ac59c72cf1 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.cpp +++ b/Core/FileSystems/VirtualDiscFileSystem.cpp @@ -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;