From 161a6cd2192c4cde6a7433f020daebbdee8dd5e6 Mon Sep 17 00:00:00 2001 From: shawly Date: Sun, 13 Sep 2026 15:31:30 +0200 Subject: [PATCH] Memcard: Reject accesses to reserved clusters in folder memcards Reads and writes below the allocation offset or past the allocation end wrapped the FAT cluster subtraction and read out of bounds. Fixes #14890. --- pcsx2/SIO/Memcard/MemoryCardFolder.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/pcsx2/SIO/Memcard/MemoryCardFolder.cpp b/pcsx2/SIO/Memcard/MemoryCardFolder.cpp index 9cc325081a..56d6dd03f4 100644 --- a/pcsx2/SIO/Memcard/MemoryCardFolder.cpp +++ b/pcsx2/SIO/Memcard/MemoryCardFolder.cpp @@ -897,7 +897,15 @@ bool FolderMemoryCard::ReadFromFile(u8* dest, u32 adr, u32 dataLength) const u32 page = adr / PageSizeRaw; const u32 offset = adr % PageSizeRaw; const u32 cluster = adr / ClusterSizeRaw; - const u32 fatCluster = cluster - m_superBlock.data.alloc_offset; + + const u32 startDataCluster = m_superBlock.data.alloc_offset; + const u32 endDataCluster = startDataCluster + m_superBlock.data.alloc_end; + if (cluster < startDataCluster || cluster >= endDataCluster) + { + return false; + } + + const u32 fatCluster = cluster - startDataCluster; // if the cluster is unused according to FAT, just return if ((m_fat.data[0][0][fatCluster] & DataClusterInUseMask) == 0) @@ -1503,7 +1511,15 @@ bool FolderMemoryCard::WriteToFile(const u8* src, u32 adr, u32 dataLength) const u32 cluster = adr / ClusterSizeRaw; const u32 page = adr / PageSizeRaw; const u32 offset = adr % PageSizeRaw; - const u32 fatCluster = cluster - m_superBlock.data.alloc_offset; + + const u32 startDataCluster = m_superBlock.data.alloc_offset; + const u32 endDataCluster = startDataCluster + m_superBlock.data.alloc_end; + if (cluster < startDataCluster || cluster >= endDataCluster) + { + return false; + } + + const u32 fatCluster = cluster - startDataCluster; // if the cluster is unused according to FAT, just skip all this, we're not gonna find anything anyway if ((m_fat.data[0][0][fatCluster] & DataClusterInUseMask) == 0)