Skip to content

Commit bc97238

Browse files
#3119 crash when lua requests debug settings value
1 parent 377d9a9 commit bc97238

File tree

2 files changed

+55
-35
lines changed

2 files changed

+55
-35
lines changed

indra/llcommon/lua_function.cpp

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,34 @@ int lua_metaipair(lua_State* L)
764764

765765
} // anonymous namespace
766766

767+
bool LuaState::push_debug_traceback()
768+
{
769+
// Push debug.traceback() onto the stack as lua_pcall()'s error
770+
// handler function. On error, lua_pcall() calls the specified error
771+
// handler function with the original error message; the message
772+
// returned by the error handler is then returned by lua_pcall().
773+
// Luau's debug.traceback() is called with a message to prepend to the
774+
// returned traceback string. Almost as if they'd been designed to
775+
// work together...
776+
lua_getglobal(mState, "debug");
777+
if (!lua_istable(mState, -1))
778+
{
779+
lua_pop(mState, 1);
780+
LL_WARNS("Lua") << "'debug' table not found" << LL_ENDL;
781+
return false;
782+
}
783+
lua_getfield(mState, -1, "traceback");
784+
if (!lua_isfunction(mState, -1))
785+
{
786+
lua_pop(mState, 2);
787+
LL_WARNS("Lua") << "'traceback' func not found" << LL_ENDL;
788+
return false;
789+
}
790+
// ditch "debug"
791+
lua_remove(mState, -2);
792+
return true;
793+
}
794+
767795
LuaState::~LuaState()
768796
{
769797
// If we're unwinding the stack due to an exception, don't bother trying
@@ -793,45 +821,35 @@ LuaState::~LuaState()
793821
LL_DEBUGS("Lua") << LLCoros::getName() << ": Registry.atexit is a table with "
794822
<< len << " entries" << LL_ENDL;
795823

796-
// Push debug.traceback() onto the stack as lua_pcall()'s error
797-
// handler function. On error, lua_pcall() calls the specified error
798-
// handler function with the original error message; the message
799-
// returned by the error handler is then returned by lua_pcall().
800-
// Luau's debug.traceback() is called with a message to prepend to the
801-
// returned traceback string. Almost as if they'd been designed to
802-
// work together...
803-
lua_getglobal(mState, "debug");
804-
lua_getfield(mState, -1, "traceback");
805-
// ditch "debug"
806-
lua_remove(mState, -2);
807-
// stack now contains atexit, debug.traceback()
808-
809-
for (int i(len); i >= 1; --i)
824+
// TODO: 'debug' global shouldn't be overwritten and should be accessible at this stage
825+
if (push_debug_traceback())
810826
{
811-
lua_pushinteger(mState, i);
812-
// stack contains Registry.atexit, debug.traceback(), i
813-
lua_gettable(mState, -3);
814-
// stack contains Registry.atexit, debug.traceback(), atexit[i]
815-
// Call atexit[i](), no args, no return values.
816-
// Use lua_pcall() because errors in any one atexit() function
817-
// shouldn't cancel the rest of them. Pass debug.traceback() as
818-
// the error handler function.
819-
LL_DEBUGS("Lua") << LLCoros::getName()
820-
<< ": calling atexit(" << i << ")" << LL_ENDL;
821-
if (lua_pcall(mState, 0, 0, -2) != LUA_OK)
827+
// stack now contains atexit, debug.traceback()
828+
for (int i(len); i >= 1; --i)
822829
{
823-
auto error{ lua_tostdstring(mState, -1) };
824-
LL_WARNS("Lua") << LLCoros::getName()
825-
<< ": atexit(" << i << ") error: " << error << LL_ENDL;
826-
// pop error message
827-
lua_pop(mState, 1);
830+
lua_pushinteger(mState, i);
831+
// stack contains Registry.atexit, debug.traceback(), i
832+
lua_gettable(mState, -3);
833+
// stack contains Registry.atexit, debug.traceback(), atexit[i]
834+
// Call atexit[i](), no args, no return values.
835+
// Use lua_pcall() because errors in any one atexit() function
836+
// shouldn't cancel the rest of them. Pass debug.traceback() as
837+
// the error handler function.
838+
LL_DEBUGS("Lua") << LLCoros::getName() << ": calling atexit(" << i << ")" << LL_ENDL;
839+
if (lua_pcall(mState, 0, 0, -2) != LUA_OK)
840+
{
841+
auto error{ lua_tostdstring(mState, -1) };
842+
LL_WARNS("Lua") << LLCoros::getName() << ": atexit(" << i << ") error: " << error << LL_ENDL;
843+
// pop error message
844+
lua_pop(mState, 1);
845+
}
846+
LL_DEBUGS("Lua") << LLCoros::getName() << ": atexit(" << i << ") done" << LL_ENDL;
847+
// lua_pcall() has already popped atexit[i]:
848+
// stack contains atexit, debug.traceback()
828849
}
829-
LL_DEBUGS("Lua") << LLCoros::getName() << ": atexit(" << i << ") done" << LL_ENDL;
830-
// lua_pcall() has already popped atexit[i]:
831-
// stack contains atexit, debug.traceback()
850+
// pop debug.traceback()
851+
lua_pop(mState, 1);
832852
}
833-
// pop debug.traceback()
834-
lua_pop(mState, 1);
835853
}
836854
// pop Registry.atexit (either table or nil)
837855
lua_pop(mState, 1);

indra/llcommon/lua_function.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ class LuaState
122122
void set_interrupts_counter(S32 counter);
123123
void check_interrupts_counter();
124124

125+
bool push_debug_traceback();
126+
125127
private:
126128
/*---------------------------- feature flag ----------------------------*/
127129
bool mFeature{ false };

0 commit comments

Comments
 (0)