aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto I <roberto@inf.puc-rio.br>2026-07-13 15:55:36 -0300
committerRoberto I <roberto@inf.puc-rio.br>2026-07-13 15:55:36 -0300
commit0f781f836ab348716eb9232d3831a871b9821a3c (patch)
tree2bdc431f9d920ae418c5ce6fb1569fb984234ed4
parent934fdd481ced3a9d4a7aaace4479ce889ab23582 (diff)
downloadlua-0f781f836ab348716eb9232d3831a871b9821a3c.tar.gz
lua-0f781f836ab348716eb9232d3831a871b9821a3c.tar.bz2
lua-0f781f836ab348716eb9232d3831a871b9821a3c.zip
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.
-rw-r--r--lvm.c7
-rw-r--r--testes/events.lua10
2 files changed, 16 insertions, 1 deletions
diff --git a/lvm.c b/lvm.c
index 7023a04d..bbadf0a6 100644
--- a/lvm.c
+++ b/lvm.c
@@ -361,7 +361,12 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
361 } 361 }
362 t = tm; /* else repeat assignment over 'tm' */ 362 t = tm; /* else repeat assignment over 'tm' */
363 if (luaV_fastget(L, t, key, slot, luaH_get)) { 363 if (luaV_fastget(L, t, key, slot, luaH_get)) {
364 luaV_finishfastset(L, t, slot, val); 364 /* execute 'luaV_finishfastset', but preserving the original 't'
365 for the barrier. 't' and 'slot' can point to the same value,
366 and so the assignment can change 't' value */
367 GCObject *h = gcvalue(t);
368 setobj2t(L, cast(TValue *,slot), val);
369 luaC_barrierback(L, h, val);
365 return; /* done */ 370 return; /* done */
366 } 371 }
367 /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ 372 /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */
diff --git a/testes/events.lua b/testes/events.lua
index def13dc8..d0a48c66 100644
--- a/testes/events.lua
+++ b/testes/events.lua
@@ -382,6 +382,16 @@ do
382end 382end
383 383
384 384
385do -- bug in 5.4
386 local parent = {}
387 parent.__newindex = parent
388 collectgarbage()
389 local child = setmetatable({}, parent)
390 child.__newindex = {x = "hello"}
391 collectgarbage("step")
392 assert(parent.__newindex.x == "hello")
393end
394
385 395
386-- concat metamethod x numbers (bug in 5.1.1) 396-- concat metamethod x numbers (bug in 5.1.1)
387c = {} 397c = {}