From 1aabd0d7945a7c533c42bf27f15937572596104f Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Thu, 2 Jul 2026 06:03:34 -0400 Subject: [PATCH] fixes memory leak in the emscripten page allocator (#25901) The emscripten branch cast the descriptor address to the value type EmscriptenMMapBlock instead of the pointer alias PEmscriptenMMapBlock, so osAllocPages stored realSize/realPointer in a discarded local and osDeallocPages reinterpreted the address integer as the descriptor instead of dereferencing it -- calling munmap() with garbage that fails, so freed pages are never returned. Freed huge chunks are also dropped from the free list, leaking permanently. Affects wasm32 and wasm64. Cast to PEmscriptenMMapBlock so both accesses go through memory. (cherry picked from commit 8101c8d73bb704e1eb783ccc079700a30efc75e1) --- lib/system/osalloc.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/system/osalloc.nim b/lib/system/osalloc.nim index 5b6a191dfc..5d171b97af 100644 --- a/lib/system/osalloc.nim +++ b/lib/system/osalloc.nim @@ -89,7 +89,7 @@ elif defined(emscripten) and not defined(StandaloneHeapSize): var mmapDescrPos = cast[int](result) -% sizeof(EmscriptenMMapBlock) - var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos) + var mmapDescr = cast[PEmscriptenMMapBlock](mmapDescrPos) mmapDescr.realSize = realSize mmapDescr.realPointer = realPointer @@ -99,7 +99,7 @@ elif defined(emscripten) and not defined(StandaloneHeapSize): proc osDeallocPages(p: pointer, size: int) {.inline.} = var mmapDescrPos = cast[int](p) -% sizeof(EmscriptenMMapBlock) - var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos) + var mmapDescr = cast[PEmscriptenMMapBlock](mmapDescrPos) munmap(mmapDescr.realPointer, mmapDescr.realSize) elif defined(genode) and not defined(StandaloneHeapSize):