diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-01-16 16:07:39 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-01-16 16:07:39 -0300 |
commit | 664bda02ba4bd167728a2acbe658cc4a9dd9b0b5 (patch) | |
tree | fc6fe196de8326e2eee3deb81e448525a362afa8 | |
parent | 2d8d5c74b5ef3d333314feede0165df7c3d13811 (diff) | |
download | lua-664bda02ba4bd167728a2acbe658cc4a9dd9b0b5.tar.gz lua-664bda02ba4bd167728a2acbe658cc4a9dd9b0b5.tar.bz2 lua-664bda02ba4bd167728a2acbe658cc4a9dd9b0b5.zip |
fixing 'lua_status' in panic.
'luaD_throw' may call 'luaE_resetthread', which returns an error code
but clears 'L->status'; so, 'luaD_throw' should set that status again.
-rw-r--r-- | ldo.c | 1 | ||||
-rw-r--r-- | ltests.c | 10 | ||||
-rw-r--r-- | testes/api.lua | 19 |
3 files changed, 28 insertions, 2 deletions
@@ -133,6 +133,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
133 | else { /* thread has no error handler */ | 133 | else { /* thread has no error handler */ |
134 | global_State *g = G(L); | 134 | global_State *g = G(L); |
135 | errcode = luaE_resetthread(L, errcode); /* close all upvalues */ | 135 | errcode = luaE_resetthread(L, errcode); /* close all upvalues */ |
136 | L->status = cast_byte(errcode); | ||
136 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ | 137 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ |
137 | setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */ | 138 | setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */ |
138 | luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ | 139 | luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ |
@@ -1367,7 +1367,7 @@ static int checkpanic (lua_State *L) { | |||
1367 | b.L = L; | 1367 | b.L = L; |
1368 | L1 = lua_newstate(f, ud, 0); /* create new state */ | 1368 | L1 = lua_newstate(f, ud, 0); /* create new state */ |
1369 | if (L1 == NULL) { /* error? */ | 1369 | if (L1 == NULL) { /* error? */ |
1370 | lua_pushnil(L); | 1370 | lua_pushstring(L, MEMERRMSG); |
1371 | return 1; | 1371 | return 1; |
1372 | } | 1372 | } |
1373 | lua_atpanic(L1, panicback); /* set its panic function */ | 1373 | lua_atpanic(L1, panicback); /* set its panic function */ |
@@ -1507,7 +1507,7 @@ static int getindex_aux (lua_State *L, lua_State *L1, const char **pc) { | |||
1507 | 1507 | ||
1508 | 1508 | ||
1509 | static const char *const statcodes[] = {"OK", "YIELD", "ERRRUN", | 1509 | static const char *const statcodes[] = {"OK", "YIELD", "ERRRUN", |
1510 | "ERRSYNTAX", MEMERRMSG, "ERRGCMM", "ERRERR"}; | 1510 | "ERRSYNTAX", MEMERRMSG, "ERRERR"}; |
1511 | 1511 | ||
1512 | /* | 1512 | /* |
1513 | ** Avoid these stat codes from being collected, to avoid possible | 1513 | ** Avoid these stat codes from being collected, to avoid possible |
@@ -1806,6 +1806,12 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) { | |||
1806 | int level = getnum; | 1806 | int level = getnum; |
1807 | luaL_traceback(L1, L1, msg, level); | 1807 | luaL_traceback(L1, L1, msg, level); |
1808 | } | 1808 | } |
1809 | else if EQ("threadstatus") { | ||
1810 | lua_pushstring(L1, statcodes[lua_status(L1)]); | ||
1811 | } | ||
1812 | else if EQ("alloccount") { | ||
1813 | l_memcontrol.countlimit = cast_uint(getnum); | ||
1814 | } | ||
1809 | else if EQ("return") { | 1815 | else if EQ("return") { |
1810 | int n = getnum; | 1816 | int n = getnum; |
1811 | if (L1 != L) { | 1817 | if (L1 != L) { |
diff --git a/testes/api.lua b/testes/api.lua index b7e34f7f..21f703fd 100644 --- a/testes/api.lua +++ b/testes/api.lua | |||
@@ -416,6 +416,10 @@ do | |||
416 | -- trivial error | 416 | -- trivial error |
417 | assert(T.checkpanic("pushstring hi; error") == "hi") | 417 | assert(T.checkpanic("pushstring hi; error") == "hi") |
418 | 418 | ||
419 | -- thread status inside panic (bug in 5.4.4) | ||
420 | assert(T.checkpanic("pushstring hi; error", "threadstatus; return 2") == | ||
421 | "ERRRUN") | ||
422 | |||
419 | -- using the stack inside panic | 423 | -- using the stack inside panic |
420 | assert(T.checkpanic("pushstring hi; error;", | 424 | assert(T.checkpanic("pushstring hi; error;", |
421 | [[checkstack 5 XX | 425 | [[checkstack 5 XX |
@@ -433,6 +437,21 @@ do | |||
433 | assert(T.checkpanic("newuserdata 20000") == MEMERRMSG) | 437 | assert(T.checkpanic("newuserdata 20000") == MEMERRMSG) |
434 | T.totalmem(0) -- restore high limit | 438 | T.totalmem(0) -- restore high limit |
435 | 439 | ||
440 | -- memory error + thread status | ||
441 | local x = T.checkpanic( | ||
442 | [[ alloccount 0 # force a memory error in next line | ||
443 | newtable | ||
444 | ]], | ||
445 | [[ | ||
446 | alloccount -1 # allow free allocations again | ||
447 | pushstring XX | ||
448 | threadstatus | ||
449 | concat 2 # to make sure message came from here | ||
450 | return 1 | ||
451 | ]]) | ||
452 | T.alloccount() | ||
453 | assert(x == "XX" .. "not enough memory") | ||
454 | |||
436 | -- stack error | 455 | -- stack error |
437 | if not _soft then | 456 | if not _soft then |
438 | local msg = T.checkpanic[[ | 457 | local msg = T.checkpanic[[ |