mirror of
https://github.com/lua/lua.git
synced 2026-07-25 07:29:05 +00:00
Bug: new metatable in weak table can fool the GC
All-weak tables are not being revisited after being visited during propagation; if it gets a new metatable after that, the new metatable may not be marked.
This commit is contained in:
8
lgc.c
8
lgc.c
@@ -553,8 +553,12 @@ static lu_mem traversetable (global_State *g, Table *h) {
|
||||
traverseweakvalue(g, h);
|
||||
else if (!weakvalue) /* strong values? */
|
||||
traverseephemeron(g, h, 0);
|
||||
else /* all weak */
|
||||
linkgclist(h, g->allweak); /* nothing to traverse now */
|
||||
else { /* all weak */
|
||||
if (g->gcstate == GCSpropagate)
|
||||
linkgclist(h, g->grayagain); /* must visit again its metatable */
|
||||
else
|
||||
linkgclist(h, g->allweak); /* must clear collected entries */
|
||||
}
|
||||
}
|
||||
else /* not weak */
|
||||
traversestrongtable(g, h);
|
||||
|
||||
@@ -301,6 +301,16 @@ collectgarbage()
|
||||
assert(next(a) == string.rep('$', 11))
|
||||
|
||||
|
||||
if T then -- bug since 5.3: all-weak tables are not being revisited
|
||||
T.gcstate("propagate")
|
||||
local t = setmetatable({}, {__mode = "kv"})
|
||||
T.gcstate("atomic") -- 't' was visited
|
||||
setmetatable(t, {__mode = "kv"})
|
||||
T.gcstate("pause") -- its new metatable is not being visited
|
||||
assert(getmetatable(t).__mode == "kv")
|
||||
end
|
||||
|
||||
|
||||
-- 'bug' in 5.1
|
||||
a = {}
|
||||
local t = {x = 10}
|
||||
|
||||
Reference in New Issue
Block a user