From b8da1106eb61fa820b6e4d28238f956425a67608 Mon Sep 17 00:00:00 2001 From: asarium Date: Sun, 31 Dec 2023 17:36:39 +0100 Subject: [PATCH] Fix unbalanced stack when retrieving Lua main thread After getting the main state from the Lua registry, this function had two Lua thread values on its Lua stack but we only removed one which lead to a value being left on the stack. Why did this not blow up before? Because undefined behavior. The only place where this was called was when creating a Lua reference value where luaL_ref is called in the same expression (see UniqueLuaReference::create). The evaluation order of the parameters for the make_shared call is not defined by the standard and for some reason all major compilers (except clang) choose to execute the luaL_ref call before the getMainThread call. For those compilers, everything is fine. We have some extra values on the Lua stack but that gets cleaned up after the API function finishes. However, clang first evaluates the getMainThread which leaves an extra Lua thread on the Lua stack. The luaL_ref call then references this thread value instead of the intended value. In the concrete case, this meant that LuaFunction saw that the reference points to a thread and rightfully threw an exception. This fixes #5904. --- code/scripting/lua/LuaUtil.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/scripting/lua/LuaUtil.cpp b/code/scripting/lua/LuaUtil.cpp index 1e967625119..043cae53f67 100644 --- a/code/scripting/lua/LuaUtil.cpp +++ b/code/scripting/lua/LuaUtil.cpp @@ -55,7 +55,9 @@ lua_State* getMainThread(lua_State* L) lua_rawget(L, LUA_REGISTRYINDEX); auto state = lua_tothread(L, -1); - lua_pop(L, 1); + + // Need to pop both the thread from L and the main thread to return the stack back to neutral + lua_pop(L, 2); return state; }