From 8101c8d73bb704e1eb783ccc079700a30efc75e1 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. --- 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 4177b47b1f..db7f4c1482 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):