diff options
-rw-r--r-- | ldebug.c | 21 | ||||
-rw-r--r-- | lgc.c | 8 | ||||
-rw-r--r-- | lparser.c | 5 | ||||
-rw-r--r-- | lstate.c | 3 | ||||
-rw-r--r-- | lua.h | 8 | ||||
-rwxr-xr-x | manual/2html | 2 | ||||
-rw-r--r-- | testes/all.lua | 2 | ||||
-rw-r--r-- | testes/coroutine.lua | 19 | ||||
-rw-r--r-- | testes/errors.lua | 4 | ||||
-rw-r--r-- | testes/gc.lua | 10 |
10 files changed, 65 insertions, 17 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; |
@@ -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; |
@@ -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); |
@@ -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 |
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/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/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} |