From c931d86e98da320c71da70c16d44aa28e9755520 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 12 Mar 2025 15:51:16 -0300 Subject: [PATCH] 'luaD_seterrorobj' should not raise errors This function can be called unprotected, so it should not raise any kind of errors. (It could raise a memory-allocation error when creating a message). --- ldebug.c | 4 ++++ ldo.c | 36 +++++++++++++++++------------------- ldo.h | 1 + lstate.c | 2 +- testes/errors.lua | 4 ++-- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/ldebug.c b/ldebug.c index 18bdc595..a3202981 100644 --- a/ldebug.c +++ b/ldebug.c @@ -832,6 +832,10 @@ l_noret luaG_errormsg (lua_State *L) { L->top.p++; /* assume EXTRA_STACK */ luaD_callnoyield(L, L->top.p - 2, 1); /* call it */ } + if (ttisnil(s2v(L->top.p - 1))) { /* error object is nil? */ + /* change it to a proper message */ + setsvalue2s(L, L->top.p - 1, luaS_newliteral(L, "")); + } luaD_throw(L, LUA_ERRRUN); } diff --git a/ldo.c b/ldo.c index 84f7bbb2..b0d37bf7 100644 --- a/ldo.c +++ b/ldo.c @@ -102,24 +102,13 @@ struct lua_longjmp { void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop) { - switch (errcode) { - case LUA_ERRMEM: { /* memory error? */ - setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ - break; - } - case LUA_ERRERR: { - setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); - break; - } - default: { - lua_assert(errorstatus(errcode)); /* must be a real error */ - if (!ttisnil(s2v(L->top.p - 1))) { /* error object is not nil? */ - setobjs2s(L, oldtop, L->top.p - 1); /* move it to 'oldtop' */ - } - else /* change it to a proper message */ - setsvalue2s(L, oldtop, luaS_newliteral(L, "")); - break; - } + if (errcode == LUA_ERRMEM) { /* memory error? */ + setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ + } + else { + lua_assert(errorstatus(errcode)); /* must be a real error */ + lua_assert(!ttisnil(s2v(L->top.p - 1))); /* with a non-nil object */ + setobjs2s(L, oldtop, L->top.p - 1); /* move it to 'oldtop' */ } L->top.p = oldtop + 1; /* top goes back to old top plus error object */ } @@ -190,6 +179,15 @@ TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { #define ERRORSTACKSIZE (MAXSTACK + STACKERRSPACE) +/* raise an error while running the message handler */ +l_noret luaD_errerr (lua_State *L) { + TString *msg = luaS_newliteral(L, "error in error handling"); + setsvalue2s(L, L->top.p, msg); + L->top.p++; /* assume EXTRA_STACK */ + luaD_throw(L, LUA_ERRERR); +} + + /* ** In ISO C, any pointer use after the pointer has been deallocated is ** undefined behavior. So, before a stack reallocation, all pointers @@ -317,7 +315,7 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) { a stack error; cannot grow further than that. */ lua_assert(stacksize(L) == ERRORSTACKSIZE); if (raiseerror) - luaD_throw(L, LUA_ERRERR); /* error inside message handler */ + luaD_errerr(L); /* error inside message handler */ return 0; /* if not 'raiseerror', just signal it */ } else if (n < MAXSTACK) { /* avoids arithmetic overflows */ diff --git a/ldo.h b/ldo.h index ea1655e1..465f4fb8 100644 --- a/ldo.h +++ b/ldo.h @@ -67,6 +67,7 @@ /* type of protected functions, to be ran by 'runprotected' */ typedef void (*Pfunc) (lua_State *L, void *ud); +LUAI_FUNC l_noret luaD_errerr (lua_State *L); LUAI_FUNC void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop); LUAI_FUNC TStatus luaD_protectedparser (lua_State *L, ZIO *z, const char *name, diff --git a/lstate.c b/lstate.c index 69ddef40..ed5ccaaa 100644 --- a/lstate.c +++ b/lstate.c @@ -132,7 +132,7 @@ void luaE_checkcstack (lua_State *L) { if (getCcalls(L) == LUAI_MAXCCALLS) luaG_runerror(L, "C stack overflow"); else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) - luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ + luaD_errerr(L); /* error while handling stack error */ } diff --git a/testes/errors.lua b/testes/errors.lua index 8ef26757..d83e6023 100644 --- a/testes/errors.lua +++ b/testes/errors.lua @@ -46,7 +46,7 @@ end assert(doit("error('hi', 0)") == 'hi') -- test nil error message -assert(doit("error()") == "") +assert(doit("error()") == "") -- test common errors/errors that crashed in the past @@ -614,7 +614,7 @@ do assert(not res and msg == t) res, msg = pcall(function () error(nil) end) - assert(not res and msg == "") + assert(not res and msg == "") local function f() error{msg='x'} end res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end)