mirror of
https://github.com/lua/lua
synced 2026-09-26 16:17:11 +03:00
Bug: Issues with write barrier for __newindex
In 'luaV_finishset', there is an update on a table that is a field on another table. If the first table is the same as the one with the field (e.g., after 't.__newindex = t'), the update can change the value on that field (if the field being updated is '__newindex' itself). After that, the barrier is called with the table stored in that field, which is not the correct table anymore.
This commit is contained in:
parent
934fdd481c
commit
0f781f836a
2 changed files with 16 additions and 1 deletions
7
lvm.c
7
lvm.c
|
|
@ -361,7 +361,12 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
|
|||
}
|
||||
t = tm; /* else repeat assignment over 'tm' */
|
||||
if (luaV_fastget(L, t, key, slot, luaH_get)) {
|
||||
luaV_finishfastset(L, t, slot, val);
|
||||
/* execute 'luaV_finishfastset', but preserving the original 't'
|
||||
for the barrier. 't' and 'slot' can point to the same value,
|
||||
and so the assignment can change 't' value */
|
||||
GCObject *h = gcvalue(t);
|
||||
setobj2t(L, cast(TValue *,slot), val);
|
||||
luaC_barrierback(L, h, val);
|
||||
return; /* done */
|
||||
}
|
||||
/* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */
|
||||
|
|
|
|||
|
|
@ -382,6 +382,16 @@ do
|
|||
end
|
||||
|
||||
|
||||
do -- bug in 5.4
|
||||
local parent = {}
|
||||
parent.__newindex = parent
|
||||
collectgarbage()
|
||||
local child = setmetatable({}, parent)
|
||||
child.__newindex = {x = "hello"}
|
||||
collectgarbage("step")
|
||||
assert(parent.__newindex.x == "hello")
|
||||
end
|
||||
|
||||
|
||||
-- concat metamethod x numbers (bug in 5.1.1)
|
||||
c = {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue