From 5c8da59fe88d92717d540e6fb061c78e62e34d42 Mon Sep 17 00:00:00 2001 From: James Huston Date: Sat, 13 Dec 2025 19:18:06 -0500 Subject: [PATCH] fix(eluna): Fix GC re-entrancy crash in CollectGarbage The CollectGarbage metamethod was calling Eluna::GetEluna(L) which uses lua_pushstring internally. This can trigger another GC cycle while already inside the GC handler, causing memory corruption and crashes. The fix avoids GetEluna entirely by directly casting the userdata to ElunaObject without type checking, which is safe since the __gc metamethod is only called on valid userdata of the correct type. This fixes crashes in SHOW_WAYPOINTS and other handlers that hold creature references when GC runs during method calls. --- src/server/game/LuaEngine/ElunaTemplate.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/server/game/LuaEngine/ElunaTemplate.h b/src/server/game/LuaEngine/ElunaTemplate.h index e20e020ca2..613837cba9 100644 --- a/src/server/game/LuaEngine/ElunaTemplate.h +++ b/src/server/game/LuaEngine/ElunaTemplate.h @@ -480,12 +480,17 @@ public: // Remember special cases like ElunaTemplate::CollectGarbage static int CollectGarbage(lua_State* L) { - Eluna* E = Eluna::GetEluna(L); - - // Get object pointer (and check type, no error) - ElunaObject* obj = E->CHECKOBJ(1, false); - if (obj) + // IMPORTANT: Do NOT call Eluna::GetEluna(L) here! + // GetEluna uses lua_pushstring which can trigger GC re-entrancy, + // causing memory corruption when we're already inside the GC handler. + // Instead, get the userdata directly without type checking. + + void* ud = lua_touserdata(L, 1); + if (ud) + { + ElunaObject* obj = static_cast(ud); obj->~ElunaObject(); + } return 0; }