diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-03-12 15:51:16 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-03-12 15:51:16 -0300 |
| commit | c931d86e98da320c71da70c16d44aa28e9755520 (patch) | |
| tree | 2c73ee84120f8f7983d883b3f46546e0676f6ba6 | |
| parent | d9e0f64a5de699a620771af299ea22f522c72f19 (diff) | |
| download | lua-c931d86e98da320c71da70c16d44aa28e9755520.tar.gz lua-c931d86e98da320c71da70c16d44aa28e9755520.tar.bz2 lua-c931d86e98da320c71da70c16d44aa28e9755520.zip | |
'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).
| -rw-r--r-- | ldebug.c | 4 | ||||
| -rw-r--r-- | ldo.c | 36 | ||||
| -rw-r--r-- | ldo.h | 1 | ||||
| -rw-r--r-- | lstate.c | 2 | ||||
| -rw-r--r-- | testes/errors.lua | 4 |
5 files changed, 25 insertions, 22 deletions
| @@ -832,6 +832,10 @@ l_noret luaG_errormsg (lua_State *L) { | |||
| 832 | L->top.p++; /* assume EXTRA_STACK */ | 832 | L->top.p++; /* assume EXTRA_STACK */ |
| 833 | luaD_callnoyield(L, L->top.p - 2, 1); /* call it */ | 833 | luaD_callnoyield(L, L->top.p - 2, 1); /* call it */ |
| 834 | } | 834 | } |
| 835 | if (ttisnil(s2v(L->top.p - 1))) { /* error object is nil? */ | ||
| 836 | /* change it to a proper message */ | ||
| 837 | setsvalue2s(L, L->top.p - 1, luaS_newliteral(L, "<no error object>")); | ||
| 838 | } | ||
| 835 | luaD_throw(L, LUA_ERRRUN); | 839 | luaD_throw(L, LUA_ERRRUN); |
| 836 | } | 840 | } |
| 837 | 841 | ||
| @@ -102,24 +102,13 @@ struct lua_longjmp { | |||
| 102 | 102 | ||
| 103 | 103 | ||
| 104 | void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop) { | 104 | void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop) { |
| 105 | switch (errcode) { | 105 | if (errcode == LUA_ERRMEM) { /* memory error? */ |
| 106 | case LUA_ERRMEM: { /* memory error? */ | 106 | setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ |
| 107 | setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ | 107 | } |
| 108 | break; | 108 | else { |
| 109 | } | 109 | lua_assert(errorstatus(errcode)); /* must be a real error */ |
| 110 | case LUA_ERRERR: { | 110 | lua_assert(!ttisnil(s2v(L->top.p - 1))); /* with a non-nil object */ |
| 111 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); | 111 | setobjs2s(L, oldtop, L->top.p - 1); /* move it to 'oldtop' */ |
| 112 | break; | ||
| 113 | } | ||
| 114 | default: { | ||
| 115 | lua_assert(errorstatus(errcode)); /* must be a real error */ | ||
| 116 | if (!ttisnil(s2v(L->top.p - 1))) { /* error object is not nil? */ | ||
| 117 | setobjs2s(L, oldtop, L->top.p - 1); /* move it to 'oldtop' */ | ||
| 118 | } | ||
| 119 | else /* change it to a proper message */ | ||
| 120 | setsvalue2s(L, oldtop, luaS_newliteral(L, "<error object is nil>")); | ||
| 121 | break; | ||
| 122 | } | ||
| 123 | } | 112 | } |
| 124 | L->top.p = oldtop + 1; /* top goes back to old top plus error object */ | 113 | L->top.p = oldtop + 1; /* top goes back to old top plus error object */ |
| 125 | } | 114 | } |
| @@ -190,6 +179,15 @@ TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
| 190 | #define ERRORSTACKSIZE (MAXSTACK + STACKERRSPACE) | 179 | #define ERRORSTACKSIZE (MAXSTACK + STACKERRSPACE) |
| 191 | 180 | ||
| 192 | 181 | ||
| 182 | /* raise an error while running the message handler */ | ||
| 183 | l_noret luaD_errerr (lua_State *L) { | ||
| 184 | TString *msg = luaS_newliteral(L, "error in error handling"); | ||
| 185 | setsvalue2s(L, L->top.p, msg); | ||
| 186 | L->top.p++; /* assume EXTRA_STACK */ | ||
| 187 | luaD_throw(L, LUA_ERRERR); | ||
| 188 | } | ||
| 189 | |||
| 190 | |||
| 193 | /* | 191 | /* |
| 194 | ** In ISO C, any pointer use after the pointer has been deallocated is | 192 | ** In ISO C, any pointer use after the pointer has been deallocated is |
| 195 | ** undefined behavior. So, before a stack reallocation, all pointers | 193 | ** undefined behavior. So, before a stack reallocation, all pointers |
| @@ -317,7 +315,7 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) { | |||
| 317 | a stack error; cannot grow further than that. */ | 315 | a stack error; cannot grow further than that. */ |
| 318 | lua_assert(stacksize(L) == ERRORSTACKSIZE); | 316 | lua_assert(stacksize(L) == ERRORSTACKSIZE); |
| 319 | if (raiseerror) | 317 | if (raiseerror) |
| 320 | luaD_throw(L, LUA_ERRERR); /* error inside message handler */ | 318 | luaD_errerr(L); /* error inside message handler */ |
| 321 | return 0; /* if not 'raiseerror', just signal it */ | 319 | return 0; /* if not 'raiseerror', just signal it */ |
| 322 | } | 320 | } |
| 323 | else if (n < MAXSTACK) { /* avoids arithmetic overflows */ | 321 | else if (n < MAXSTACK) { /* avoids arithmetic overflows */ |
| @@ -67,6 +67,7 @@ | |||
| 67 | /* type of protected functions, to be ran by 'runprotected' */ | 67 | /* type of protected functions, to be ran by 'runprotected' */ |
| 68 | typedef void (*Pfunc) (lua_State *L, void *ud); | 68 | typedef void (*Pfunc) (lua_State *L, void *ud); |
| 69 | 69 | ||
| 70 | LUAI_FUNC l_noret luaD_errerr (lua_State *L); | ||
| 70 | LUAI_FUNC void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop); | 71 | LUAI_FUNC void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop); |
| 71 | LUAI_FUNC TStatus luaD_protectedparser (lua_State *L, ZIO *z, | 72 | LUAI_FUNC TStatus luaD_protectedparser (lua_State *L, ZIO *z, |
| 72 | const char *name, | 73 | const char *name, |
| @@ -132,7 +132,7 @@ void luaE_checkcstack (lua_State *L) { | |||
| 132 | if (getCcalls(L) == LUAI_MAXCCALLS) | 132 | if (getCcalls(L) == LUAI_MAXCCALLS) |
| 133 | luaG_runerror(L, "C stack overflow"); | 133 | luaG_runerror(L, "C stack overflow"); |
| 134 | else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) | 134 | else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) |
| 135 | luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ | 135 | luaD_errerr(L); /* error while handling stack error */ |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | 138 | ||
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 | |||
| 46 | assert(doit("error('hi', 0)") == 'hi') | 46 | assert(doit("error('hi', 0)") == 'hi') |
| 47 | 47 | ||
| 48 | -- test nil error message | 48 | -- test nil error message |
| 49 | assert(doit("error()") == "<error object is nil>") | 49 | assert(doit("error()") == "<no error object>") |
| 50 | 50 | ||
| 51 | 51 | ||
| 52 | -- test common errors/errors that crashed in the past | 52 | -- test common errors/errors that crashed in the past |
| @@ -614,7 +614,7 @@ do | |||
| 614 | assert(not res and msg == t) | 614 | assert(not res and msg == t) |
| 615 | 615 | ||
| 616 | res, msg = pcall(function () error(nil) end) | 616 | res, msg = pcall(function () error(nil) end) |
| 617 | assert(not res and msg == "<error object is nil>") | 617 | assert(not res and msg == "<no error object>") |
| 618 | 618 | ||
| 619 | local function f() error{msg='x'} end | 619 | local function f() error{msg='x'} end |
| 620 | res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end) | 620 | res, msg = xpcall(f, function (r) return {msg=r.msg..'y'} end) |
