diff --git a/core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp b/core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp index 1fae6ec14..4f261f154 100644 --- a/core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp +++ b/core/libs/prx/libkernel/DirectMemory/DirectMemory.cpp @@ -923,6 +923,7 @@ int DoMunmap(void* addr, size_t len) { Trace("unmap %p+0x%zx", addr, len); if (len == 0 || (len & (PS5_PAGE_SIZE - 1)) != 0 || !addr) return SCE_KERNEL_ERROR_EINVAL; GuestAllocations::Mutation mutation; + if (!mutation.Overlaps(addr, len)) return 0; UnmapRegistered(mutation, addr, len); return 0; } diff --git a/core/libs/tests/GuestMemory.cpp b/core/libs/tests/GuestMemory.cpp index bfab22098..4897c7008 100644 --- a/core/libs/tests/GuestMemory.cpp +++ b/core/libs/tests/GuestMemory.cpp @@ -1672,6 +1672,28 @@ static void CheckAvailableDirectMemoryIsLargestFreeBlock() { Require(start == top && size == static_cast(window)); } +static void CheckMunmapOverUnmappedPages() { + constexpr std::size_t page = 0x4000; + const auto failed = reinterpret_cast(static_cast(-1)); + void* raw = mmap_nid_postfix(nullptr, page * 3, 3, 0x1002, -1, 0); + Require(raw != failed); + auto* memory = static_cast(raw); + memory[0] = 1; + memory[page * 2] = 2; + Require(munmap_nid_postfix(memory + page, page) == 0); + Require(munmap_nid_postfix(memory, page * 3) == 0); + { + GuestAllocations::Mutation mutation; + Require(!mutation.Overlaps(memory, page * 3)); + } + VirtualQueryInfo info{}; + Require(sceKernelVirtualQuery(memory, 0, &info, sizeof(info)) == SCE_KERNEL_ERROR_EACCES); + Require(sceKernelVirtualQuery(memory + page * 2, 0, &info, sizeof(info)) == SCE_KERNEL_ERROR_EACCES); + Require(munmap_nid_postfix(memory, page * 3) == 0); + Require(sceKernelMunmap(memory, page * 3) == 0); + Require(sceKernelMunmap(memory, 0) == SCE_KERNEL_ERROR_EINVAL); +} + int main() { #ifdef _WIN32 _putenv_s("APS5_PIN_WAIT_MS", "1000"); @@ -1681,6 +1703,7 @@ int main() { CheckVirtualQueryForNonReadableGuestRange(); CheckReleaseFlexibleMemory(); CheckVirtualQueryPartialMunmap(); + CheckMunmapOverUnmappedPages(); CheckNamedAndHintedMappings(); CheckInternalNamedFlexibleMapping(); CheckBatchMapStopsAtInvalidEntry(); @@ -1793,7 +1816,7 @@ int main() { Require(munmap_nid_postfix(memory, page) == 0); Require(memory[page * 2] == 73); Require(munmap_nid_postfix(memory + page * 2, page) == 0); - Require(munmap_nid_postfix(memory, page) == -1); + Require(munmap_nid_postfix(memory, page) == 0); Require(madvise_nid_postfix(memory, page, 4) == 0); *__error_nid_postfix() = 0; Require(mprotect_nid_postfix(memory, page, 1) == -1 && *__error_nid_postfix() == 22);