diff options
-rw-r--r-- | ldebug.c | 21 | ||||
-rw-r--r-- | ldo.c | 17 | ||||
-rw-r--r-- | ldo.h | 1 | ||||
-rw-r--r-- | lgc.c | 8 | ||||
-rw-r--r-- | lparser.c | 5 | ||||
-rw-r--r-- | lstate.c | 5 | ||||
-rw-r--r-- | ltests.c | 3 | ||||
-rw-r--r-- | lua.h | 8 | ||||
-rw-r--r-- | lvm.c | 3 | ||||
-rwxr-xr-x | manual/2html | 2 | ||||
-rw-r--r-- | testes/all.lua | 2 | ||||
-rw-r--r-- | testes/api.lua | 4 | ||||
-rw-r--r-- | testes/coroutine.lua | 19 | ||||
-rw-r--r-- | testes/errors.lua | 4 | ||||
-rw-r--r-- | testes/events.lua | 13 | ||||
-rw-r--r-- | testes/gc.lua | 10 |
16 files changed, 102 insertions, 23 deletions
@@ -37,6 +37,9 @@ | |||
37 | static const char *funcnamefromcall (lua_State *L, CallInfo *ci, | 37 | static const char *funcnamefromcall (lua_State *L, CallInfo *ci, |
38 | const char **name); | 38 | const char **name); |
39 | 39 | ||
40 | static const char strlocal[] = "local"; | ||
41 | static const char strupval[] = "upvalue"; | ||
42 | |||
40 | 43 | ||
41 | static int currentpc (CallInfo *ci) { | 44 | static int currentpc (CallInfo *ci) { |
42 | lua_assert(isLua(ci)); | 45 | lua_assert(isLua(ci)); |
@@ -497,7 +500,7 @@ static const char *basicgetobjname (const Proto *p, int *ppc, int reg, | |||
497 | int pc = *ppc; | 500 | int pc = *ppc; |
498 | *name = luaF_getlocalname(p, reg + 1, pc); | 501 | *name = luaF_getlocalname(p, reg + 1, pc); |
499 | if (*name) /* is a local? */ | 502 | if (*name) /* is a local? */ |
500 | return "local"; | 503 | return strlocal; |
501 | /* else try symbolic execution */ | 504 | /* else try symbolic execution */ |
502 | *ppc = pc = findsetreg(p, pc, reg); | 505 | *ppc = pc = findsetreg(p, pc, reg); |
503 | if (pc != -1) { /* could find instruction? */ | 506 | if (pc != -1) { /* could find instruction? */ |
@@ -512,7 +515,7 @@ static const char *basicgetobjname (const Proto *p, int *ppc, int reg, | |||
512 | } | 515 | } |
513 | case OP_GETUPVAL: { | 516 | case OP_GETUPVAL: { |
514 | *name = upvalname(p, GETARG_B(i)); | 517 | *name = upvalname(p, GETARG_B(i)); |
515 | return "upvalue"; | 518 | return strupval; |
516 | } | 519 | } |
517 | case OP_LOADK: return kname(p, GETARG_Bx(i), name); | 520 | case OP_LOADK: return kname(p, GETARG_Bx(i), name); |
518 | case OP_LOADKX: return kname(p, GETARG_Ax(p->code[pc + 1]), name); | 521 | case OP_LOADKX: return kname(p, GETARG_Ax(p->code[pc + 1]), name); |
@@ -547,15 +550,21 @@ static void rkname (const Proto *p, int pc, Instruction i, const char **name) { | |||
547 | 550 | ||
548 | /* | 551 | /* |
549 | ** Check whether table being indexed by instruction 'i' is the | 552 | ** Check whether table being indexed by instruction 'i' is the |
550 | ** environment '_ENV' | 553 | ** environment '_ENV'. If the table is an upvalue, get its name; |
554 | ** otherwise, find some "name" for the table and check whether | ||
555 | ** that name is the name of a local variable (and not, for instance, | ||
556 | ** a string). Then check that, if there is a name, it is '_ENV'. | ||
551 | */ | 557 | */ |
552 | static const char *isEnv (const Proto *p, int pc, Instruction i, int isup) { | 558 | static const char *isEnv (const Proto *p, int pc, Instruction i, int isup) { |
553 | int t = GETARG_B(i); /* table index */ | 559 | int t = GETARG_B(i); /* table index */ |
554 | const char *name; /* name of indexed variable */ | 560 | const char *name; /* name of indexed variable */ |
555 | if (isup) /* is 't' an upvalue? */ | 561 | if (isup) /* is 't' an upvalue? */ |
556 | name = upvalname(p, t); | 562 | name = upvalname(p, t); |
557 | else /* 't' is a register */ | 563 | else { /* 't' is a register */ |
558 | basicgetobjname(p, &pc, t, &name); | 564 | const char *what = basicgetobjname(p, &pc, t, &name); |
565 | if (what != strlocal && what != strupval) | ||
566 | name = NULL; /* cannot be the variable _ENV */ | ||
567 | } | ||
559 | return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field"; | 568 | return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field"; |
560 | } | 569 | } |
561 | 570 | ||
@@ -701,7 +710,7 @@ static const char *getupvalname (CallInfo *ci, const TValue *o, | |||
701 | for (i = 0; i < c->nupvalues; i++) { | 710 | for (i = 0; i < c->nupvalues; i++) { |
702 | if (c->upvals[i]->v.p == o) { | 711 | if (c->upvals[i]->v.p == o) { |
703 | *name = upvalname(c->p, i); | 712 | *name = upvalname(c->p, i); |
704 | return "upvalue"; | 713 | return strupval; |
705 | } | 714 | } |
706 | } | 715 | } |
707 | return NULL; | 716 | return NULL; |
@@ -94,10 +94,6 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { | |||
94 | setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ | 94 | setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ |
95 | break; | 95 | break; |
96 | } | 96 | } |
97 | case LUA_ERRERR: { | ||
98 | setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); | ||
99 | break; | ||
100 | } | ||
101 | case LUA_OK: { /* special case only for closing upvalues */ | 97 | case LUA_OK: { /* special case only for closing upvalues */ |
102 | setnilvalue(s2v(oldtop)); /* no error message */ | 98 | setnilvalue(s2v(oldtop)); /* no error message */ |
103 | break; | 99 | break; |
@@ -120,6 +116,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
120 | else { /* thread has no error handler */ | 116 | else { /* thread has no error handler */ |
121 | global_State *g = G(L); | 117 | global_State *g = G(L); |
122 | errcode = luaE_resetthread(L, errcode); /* close all upvalues */ | 118 | errcode = luaE_resetthread(L, errcode); /* close all upvalues */ |
119 | L->status = errcode; | ||
123 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ | 120 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ |
124 | setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */ | 121 | setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */ |
125 | luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ | 122 | luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ |
@@ -198,6 +195,16 @@ static void correctstack (lua_State *L) { | |||
198 | /* some space for error handling */ | 195 | /* some space for error handling */ |
199 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) | 196 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) |
200 | 197 | ||
198 | |||
199 | /* raise an error while running the message handler */ | ||
200 | l_noret luaD_errerr (lua_State *L) { | ||
201 | TString *msg = luaS_newliteral(L, "error in error handling"); | ||
202 | setsvalue2s(L, L->top.p, msg); | ||
203 | L->top.p++; /* assume EXTRA_STACK */ | ||
204 | luaD_throw(L, LUA_ERRERR); | ||
205 | } | ||
206 | |||
207 | |||
201 | /* | 208 | /* |
202 | ** Reallocate the stack to a new size, correcting all pointers into it. | 209 | ** Reallocate the stack to a new size, correcting all pointers into it. |
203 | ** In ISO C, any pointer use after the pointer has been deallocated is | 210 | ** In ISO C, any pointer use after the pointer has been deallocated is |
@@ -247,7 +254,7 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) { | |||
247 | a stack error; cannot grow further than that. */ | 254 | a stack error; cannot grow further than that. */ |
248 | lua_assert(stacksize(L) == ERRORSTACKSIZE); | 255 | lua_assert(stacksize(L) == ERRORSTACKSIZE); |
249 | if (raiseerror) | 256 | if (raiseerror) |
250 | luaD_throw(L, LUA_ERRERR); /* error inside message handler */ | 257 | luaD_errerr(L); /* error inside message handler */ |
251 | return 0; /* if not 'raiseerror', just signal it */ | 258 | return 0; /* if not 'raiseerror', just signal it */ |
252 | } | 259 | } |
253 | else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */ | 260 | else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */ |
@@ -60,6 +60,7 @@ | |||
60 | /* type of protected functions, to be ran by 'runprotected' */ | 60 | /* type of protected functions, to be ran by 'runprotected' */ |
61 | typedef void (*Pfunc) (lua_State *L, void *ud); | 61 | typedef void (*Pfunc) (lua_State *L, void *ud); |
62 | 62 | ||
63 | LUAI_FUNC l_noret luaD_errerr (lua_State *L); | ||
63 | LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); | 64 | LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); |
64 | LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, | 65 | LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, |
65 | const char *mode); | 66 | const char *mode); |
@@ -553,8 +553,12 @@ static lu_mem traversetable (global_State *g, Table *h) { | |||
553 | traverseweakvalue(g, h); | 553 | traverseweakvalue(g, h); |
554 | else if (!weakvalue) /* strong values? */ | 554 | else if (!weakvalue) /* strong values? */ |
555 | traverseephemeron(g, h, 0); | 555 | traverseephemeron(g, h, 0); |
556 | else /* all weak */ | 556 | else { /* all weak */ |
557 | linkgclist(h, g->allweak); /* nothing to traverse now */ | 557 | if (g->gcstate == GCSpropagate) |
558 | linkgclist(h, g->grayagain); /* must visit again its metatable */ | ||
559 | else | ||
560 | linkgclist(h, g->allweak); /* must clear collected entries */ | ||
561 | } | ||
558 | } | 562 | } |
559 | else /* not weak */ | 563 | else /* not weak */ |
560 | traversestrongtable(g, h); | 564 | traversestrongtable(g, h); |
@@ -849,12 +849,11 @@ static void recfield (LexState *ls, ConsControl *cc) { | |||
849 | FuncState *fs = ls->fs; | 849 | FuncState *fs = ls->fs; |
850 | int reg = ls->fs->freereg; | 850 | int reg = ls->fs->freereg; |
851 | expdesc tab, key, val; | 851 | expdesc tab, key, val; |
852 | if (ls->t.token == TK_NAME) { | 852 | if (ls->t.token == TK_NAME) |
853 | checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); | ||
854 | codename(ls, &key); | 853 | codename(ls, &key); |
855 | } | ||
856 | else /* ls->t.token == '[' */ | 854 | else /* ls->t.token == '[' */ |
857 | yindex(ls, &key); | 855 | yindex(ls, &key); |
856 | checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); | ||
858 | cc->nh++; | 857 | cc->nh++; |
859 | checknext(ls, '='); | 858 | checknext(ls, '='); |
860 | tab = *cc->t; | 859 | tab = *cc->t; |
@@ -166,7 +166,7 @@ void luaE_checkcstack (lua_State *L) { | |||
166 | if (getCcalls(L) == LUAI_MAXCCALLS) | 166 | if (getCcalls(L) == LUAI_MAXCCALLS) |
167 | luaG_runerror(L, "C stack overflow"); | 167 | luaG_runerror(L, "C stack overflow"); |
168 | else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) | 168 | else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) |
169 | luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ | 169 | luaD_errerr(L); /* error while handling stack error */ |
170 | } | 170 | } |
171 | 171 | ||
172 | 172 | ||
@@ -272,7 +272,9 @@ static void close_state (lua_State *L) { | |||
272 | luaC_freeallobjects(L); /* just collect its objects */ | 272 | luaC_freeallobjects(L); /* just collect its objects */ |
273 | else { /* closing a fully built state */ | 273 | else { /* closing a fully built state */ |
274 | L->ci = &L->base_ci; /* unwind CallInfo list */ | 274 | L->ci = &L->base_ci; /* unwind CallInfo list */ |
275 | L->errfunc = 0; /* stack unwind can "throw away" the error function */ | ||
275 | luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */ | 276 | luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */ |
277 | L->top.p = L->stack.p + 1; /* empty the stack to run finalizers */ | ||
276 | luaC_freeallobjects(L); /* collect all objects */ | 278 | luaC_freeallobjects(L); /* collect all objects */ |
277 | luai_userstateclose(L); | 279 | luai_userstateclose(L); |
278 | } | 280 | } |
@@ -328,6 +330,7 @@ int luaE_resetthread (lua_State *L, int status) { | |||
328 | if (status == LUA_YIELD) | 330 | if (status == LUA_YIELD) |
329 | status = LUA_OK; | 331 | status = LUA_OK; |
330 | L->status = LUA_OK; /* so it can run __close metamethods */ | 332 | L->status = LUA_OK; /* so it can run __close metamethods */ |
333 | L->errfunc = 0; /* stack unwind can "throw away" the error function */ | ||
331 | status = luaD_closeprotected(L, 1, status); | 334 | status = luaD_closeprotected(L, 1, status); |
332 | if (status != LUA_OK) /* errors? */ | 335 | if (status != LUA_OK) /* errors? */ |
333 | luaD_seterrorobj(L, status, L->stack.p + 1); | 336 | luaD_seterrorobj(L, status, L->stack.p + 1); |
@@ -1655,6 +1655,9 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) { | |||
1655 | int level = getnum; | 1655 | int level = getnum; |
1656 | luaL_traceback(L1, L1, msg, level); | 1656 | luaL_traceback(L1, L1, msg, level); |
1657 | } | 1657 | } |
1658 | else if EQ("threadstatus") { | ||
1659 | lua_pushstring(L1, statcodes[lua_status(L1)]); | ||
1660 | } | ||
1658 | else if EQ("return") { | 1661 | else if EQ("return") { |
1659 | int n = getnum; | 1662 | int n = getnum; |
1660 | if (L1 != L) { | 1663 | if (L1 != L) { |
@@ -18,14 +18,14 @@ | |||
18 | 18 | ||
19 | #define LUA_VERSION_MAJOR "5" | 19 | #define LUA_VERSION_MAJOR "5" |
20 | #define LUA_VERSION_MINOR "4" | 20 | #define LUA_VERSION_MINOR "4" |
21 | #define LUA_VERSION_RELEASE "7" | 21 | #define LUA_VERSION_RELEASE "8" |
22 | 22 | ||
23 | #define LUA_VERSION_NUM 504 | 23 | #define LUA_VERSION_NUM 504 |
24 | #define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 7) | 24 | #define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 8) |
25 | 25 | ||
26 | #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR | 26 | #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR |
27 | #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE | 27 | #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE |
28 | #define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2024 Lua.org, PUC-Rio" | 28 | #define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2025 Lua.org, PUC-Rio" |
29 | #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" | 29 | #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" |
30 | 30 | ||
31 | 31 | ||
@@ -497,7 +497,7 @@ struct lua_Debug { | |||
497 | 497 | ||
498 | 498 | ||
499 | /****************************************************************************** | 499 | /****************************************************************************** |
500 | * Copyright (C) 1994-2024 Lua.org, PUC-Rio. | 500 | * Copyright (C) 1994-2025 Lua.org, PUC-Rio. |
501 | * | 501 | * |
502 | * Permission is hereby granted, free of charge, to any person obtaining | 502 | * Permission is hereby granted, free of charge, to any person obtaining |
503 | * a copy of this software and associated documentation files (the | 503 | * a copy of this software and associated documentation files (the |
@@ -339,7 +339,10 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | |||
339 | lua_assert(isempty(slot)); /* slot must be empty */ | 339 | lua_assert(isempty(slot)); /* slot must be empty */ |
340 | tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ | 340 | tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ |
341 | if (tm == NULL) { /* no metamethod? */ | 341 | if (tm == NULL) { /* no metamethod? */ |
342 | sethvalue2s(L, L->top.p, h); /* anchor 't' */ | ||
343 | L->top.p++; /* assume EXTRA_STACK */ | ||
342 | luaH_finishset(L, h, key, slot, val); /* set new value */ | 344 | luaH_finishset(L, h, key, slot, val); /* set new value */ |
345 | L->top.p--; | ||
343 | invalidateTMcache(h); | 346 | invalidateTMcache(h); |
344 | luaC_barrierback(L, obj2gco(h), val); | 347 | luaC_barrierback(L, obj2gco(h), val); |
345 | return; | 348 | return; |
diff --git a/manual/2html b/manual/2html index 4a3e5771..1588c1e6 100755 --- a/manual/2html +++ b/manual/2html | |||
@@ -30,7 +30,7 @@ by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes | |||
30 | <p> | 30 | <p> |
31 | <small> | 31 | <small> |
32 | <a href="http://www.lua.org/copyright.html">Copyright</a> | 32 | <a href="http://www.lua.org/copyright.html">Copyright</a> |
33 | © 2024 Lua.org, PUC-Rio. All rights reserved. | 33 | © 2025 Lua.org, PUC-Rio. All rights reserved. |
34 | </small> | 34 | </small> |
35 | <hr> | 35 | <hr> |
36 | 36 | ||
diff --git a/testes/all.lua b/testes/all.lua index 5df0ff9b..413d4da2 100644 --- a/testes/all.lua +++ b/testes/all.lua | |||
@@ -287,7 +287,7 @@ print("final OK !!!") | |||
287 | 287 | ||
288 | --[[ | 288 | --[[ |
289 | ***************************************************************************** | 289 | ***************************************************************************** |
290 | * Copyright (C) 1994-2016 Lua.org, PUC-Rio. | 290 | * Copyright (C) 1994-2025 Lua.org, PUC-Rio. |
291 | * | 291 | * |
292 | * Permission is hereby granted, free of charge, to any person obtaining | 292 | * Permission is hereby granted, free of charge, to any person obtaining |
293 | * a copy of this software and associated documentation files (the | 293 | * a copy of this software and associated documentation files (the |
diff --git a/testes/api.lua b/testes/api.lua index 752ff18f..eab3059b 100644 --- a/testes/api.lua +++ b/testes/api.lua | |||
@@ -399,6 +399,10 @@ do | |||
399 | -- trivial error | 399 | -- trivial error |
400 | assert(T.checkpanic("pushstring hi; error") == "hi") | 400 | assert(T.checkpanic("pushstring hi; error") == "hi") |
401 | 401 | ||
402 | -- thread status inside panic (bug in 5.4.4) | ||
403 | assert(T.checkpanic("pushstring hi; error", "threadstatus; return 2") == | ||
404 | "ERRRUN") | ||
405 | |||
402 | -- using the stack inside panic | 406 | -- using the stack inside panic |
403 | assert(T.checkpanic("pushstring hi; error;", | 407 | assert(T.checkpanic("pushstring hi; error;", |
404 | [[checkstack 5 XX | 408 | [[checkstack 5 XX |
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index e566c86e..03e04451 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
@@ -493,6 +493,25 @@ assert(not pcall(a, a)) | |||
493 | a = nil | 493 | a = nil |
494 | 494 | ||
495 | 495 | ||
496 | do | ||
497 | -- bug in 5.4: thread can use message handler higher in the stack | ||
498 | -- than the variable being closed | ||
499 | local c = coroutine.create(function() | ||
500 | local clo <close> = setmetatable({}, {__close=function() | ||
501 | local x = 134 -- will overwrite message handler | ||
502 | error(x) | ||
503 | end}) | ||
504 | -- yields coroutine but leaves a new message handler for it, | ||
505 | -- that would be used when closing the coroutine (except that it | ||
506 | -- will be overwritten) | ||
507 | xpcall(coroutine.yield, function() return "XXX" end) | ||
508 | end) | ||
509 | |||
510 | assert(coroutine.resume(c)) -- start coroutine | ||
511 | local st, msg = coroutine.close(c) | ||
512 | assert(not st and msg == 134) | ||
513 | end | ||
514 | |||
496 | -- access to locals of erroneous coroutines | 515 | -- access to locals of erroneous coroutines |
497 | local x = coroutine.create (function () | 516 | local x = coroutine.create (function () |
498 | local a = 10 | 517 | local a = 10 |
diff --git a/testes/errors.lua b/testes/errors.lua index 80d91a92..15401b4f 100644 --- a/testes/errors.lua +++ b/testes/errors.lua | |||
@@ -137,6 +137,10 @@ checkmessage("aaa=(1)..{}", "a table value") | |||
137 | -- bug in 5.4.6 | 137 | -- bug in 5.4.6 |
138 | checkmessage("a = {_ENV = {}}; print(a._ENV.x + 1)", "field 'x'") | 138 | checkmessage("a = {_ENV = {}}; print(a._ENV.x + 1)", "field 'x'") |
139 | 139 | ||
140 | -- a similar bug in 5.4.7, since 5.4.0 | ||
141 | checkmessage("print(('_ENV').x + 1)", "field 'x'") | ||
142 | |||
143 | |||
140 | _G.aaa, _G.bbbb = nil | 144 | _G.aaa, _G.bbbb = nil |
141 | 145 | ||
142 | -- calls | 146 | -- calls |
diff --git a/testes/events.lua b/testes/events.lua index 8d8563b9..def13dc8 100644 --- a/testes/events.lua +++ b/testes/events.lua | |||
@@ -370,6 +370,19 @@ x = 0 .."a".."b"..c..d.."e".."f".."g" | |||
370 | assert(x.val == "0abcdefg") | 370 | assert(x.val == "0abcdefg") |
371 | 371 | ||
372 | 372 | ||
373 | do | ||
374 | -- bug since 5.4.1 | ||
375 | local mt = setmetatable({__newindex={}}, {__mode='v'}) | ||
376 | local t = setmetatable({}, mt) | ||
377 | |||
378 | if T then T.allocfailnext() end | ||
379 | |||
380 | -- seg. fault | ||
381 | for i=1, 10 do t[i] = 1 end | ||
382 | end | ||
383 | |||
384 | |||
385 | |||
373 | -- concat metamethod x numbers (bug in 5.1.1) | 386 | -- concat metamethod x numbers (bug in 5.1.1) |
374 | c = {} | 387 | c = {} |
375 | local x | 388 | local x |
diff --git a/testes/gc.lua b/testes/gc.lua index 03093e34..f017f330 100644 --- a/testes/gc.lua +++ b/testes/gc.lua | |||
@@ -301,6 +301,16 @@ collectgarbage() | |||
301 | assert(next(a) == string.rep('$', 11)) | 301 | assert(next(a) == string.rep('$', 11)) |
302 | 302 | ||
303 | 303 | ||
304 | if T then -- bug since 5.3: all-weak tables are not being revisited | ||
305 | T.gcstate("propagate") | ||
306 | local t = setmetatable({}, {__mode = "kv"}) | ||
307 | T.gcstate("atomic") -- 't' was visited | ||
308 | setmetatable(t, {__mode = "kv"}) | ||
309 | T.gcstate("pause") -- its new metatable is not being visited | ||
310 | assert(getmetatable(t).__mode == "kv") | ||
311 | end | ||
312 | |||
313 | |||
304 | -- 'bug' in 5.1 | 314 | -- 'bug' in 5.1 |
305 | a = {} | 315 | a = {} |
306 | local t = {x = 10} | 316 | local t = {x = 10} |