[Posix] Fix DeallocFixed crashes / memory leaks

BaseHeap::Dispose() walks the page table and calls
DeallocFixed(addr, 0, kRelease) for every allocated page region.
These addresses are within file-backed view mappings (i.e. guest memory).
On Windows, VirtualFree on file-mapped pages silently returns FALSE.
On POSIX, the code hit assert_always() and crashed. Changed to return false
to match Windows behavior.

Memory leaks from munmap(addr, 0):

Callers passed length=0 to DeallocFixed(kRelease). On Windows this works because
VirtualFree(addr, 0, MEM_RELEASE) means "release the entire region" — Windows
ignores the length parameter for MEM_RELEASE and always frees the whole
allocation. On POSIX, munmap(addr, 0) fails with EINVAL, so the memory was
silently leaked every time.
This commit is contained in:
Herman S.
2026-02-15 14:37:28 +09:00
parent b7add3e0ec
commit bf6e1a81eb
4 changed files with 8 additions and 6 deletions

View File

@@ -171,7 +171,7 @@ bool DeallocFixed(void* base_address, size_t length,
case DeallocationType::kDecommit:
return Protect(base_address, length, PageAccess::kNoAccess);
case DeallocationType::kRelease:
assert_always("Error: Tried to release mapped memory!");
return false;
default:
assert_unhandled_case(deallocation_type);
}

View File

@@ -38,7 +38,7 @@ X64CodeCache::X64CodeCache() = default;
X64CodeCache::~X64CodeCache() {
if (indirection_table_base_) {
xe::memory::DeallocFixed(indirection_table_base_, 0,
xe::memory::DeallocFixed(indirection_table_base_, kIndirectionTableSize,
xe::memory::DeallocationType::kRelease);
}

View File

@@ -1291,7 +1291,8 @@ uintptr_t X64Emitter::PlaceConstData() {
}
void X64Emitter::FreeConstData(uintptr_t data) {
memory::DeallocFixed(reinterpret_cast<void*>(data), 0,
memory::DeallocFixed(reinterpret_cast<void*>(data),
xe::round_up(kConstDataSize, memory::page_size()),
memory::DeallocationType::kRelease);
}

View File

@@ -56,9 +56,10 @@ static void* AllocateContext() {
}
static void FreeContext(void* ctx) {
char* true_start_of_ctx = &reinterpret_cast<char*>(
ctx)[-static_cast<ptrdiff_t>(xe::memory::allocation_granularity())];
memory::DeallocFixed(true_start_of_ctx, 0,
size_t granularity = xe::memory::allocation_granularity();
char* true_start_of_ctx =
&reinterpret_cast<char*>(ctx)[-static_cast<ptrdiff_t>(granularity)];
memory::DeallocFixed(true_start_of_ctx, granularity + sizeof(ppc::PPCContext),
memory::DeallocationType::kRelease);
}