Skip to content

fix(LuaEngine): Preallocate Lua stack size in PushRefsFor to prevent reallocation during push loop#381

Open
mostlynick3 wants to merge 4 commits intoazerothcore:masterfrom
mostlynick3:master
Open

fix(LuaEngine): Preallocate Lua stack size in PushRefsFor to prevent reallocation during push loop#381
mostlynick3 wants to merge 4 commits intoazerothcore:masterfrom
mostlynick3:master

Conversation

@mostlynick3
Copy link
Copy Markdown

@mostlynick3 mostlynick3 commented May 3, 2026

I recently ran into a problem where I ended up having so many hooks (up to 50) and functions (some 100) called on player commands that I kept getting random crashes and stack corruptions. After some troubleshooting, I found out that when the Lua stack runs out of allocated space during PushRefsFor, Lua triggers luaD_reallocstack mid-loop, moving the stack to a new memory location. This invalidates raw pointers (cl, base, k, ra) held by any luaV_execute frame on the C stack, causing a crash.

For example, this script on a clean project crashes on reaching reload conf:

local function OnCommand(event, player, command)
    if command == "test" then
        return false
    end
end
for i = 1, 500 do
    RegisterPlayerEvent(42, OnCommand)
end
CreateLuaEvent(function()
    RunCommand("reload conf")
end, 1000)

Whereas with the fix, 500 loops works correctly and I can even increase it to 50 000 without any stack corruption:

local function OnCommand(event, player, command)
    if command == "test" then
        return false
    end
end
for i = 1, 50000 do
    RegisterPlayerEvent(42, OnCommand)
end
CreateLuaEvent(function()
    RunCommand("reload conf")
end, 1000)

The fix is a single lua_checkstack(L, list.size()) call before the push loop in PushRefsFor, preallocating enough stack space for all function refs upfront so no reallocation occurs mid-loop. Now, the stack is safe until it overflows, instead of randomly corrupting.

@iThorgrim iThorgrim requested review from Copilot and iThorgrim May 3, 2026 07:53
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses Lua stack reallocation during BindingMap::PushRefsFor, which can lead to stack corruption/crashes when a large number of hook/function refs are pushed in a loop (e.g., many registered handlers).

Changes:

  • Preallocates Lua stack capacity before pushing a binding list’s function references by calling lua_checkstack(L, list.size()).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/LuaEngine/BindingMap.h
Add error log, PANIC: unprotected error in call to Lua API (stack overflow (not enough stack space to push function bindings))
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.

Comment on lines 193 to 195
BindingList& list = result->second;
luaL_checkstack(L, static_cast<int>(list.size()), "not enough stack space to push function bindings");
for (auto i = list.begin(); i != list.end();)
return;

BindingList& list = result->second;
luaL_checkstack(L, static_cast<int>(list.size()), "not enough stack space to push function bindings");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants