From c2dc6e8e947ed0c7b18d452592f722f56ee1f96a Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 14 Mar 2025 12:37:19 -0300 Subject: Missing GC barrier in 'luaV_finishset' --- lapi.c | 3 +-- lvm.c | 4 +++- testes/gc.lua | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lapi.c b/lapi.c index eab12cac..f59430a7 100644 --- a/lapi.c +++ b/lapi.c @@ -888,9 +888,8 @@ LUA_API void lua_settable (lua_State *L, int idx) { api_checkpop(L, 2); t = index2value(L, idx); luaV_fastset(t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres, luaH_pset); - if (hres == HOK) { + if (hres == HOK) luaV_finishfastset(L, t, s2v(L->top.p - 1)); - } else luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres); L->top.p -= 2; /* pop index and value */ diff --git a/lvm.c b/lvm.c index af048d81..f14397d4 100644 --- a/lvm.c +++ b/lvm.c @@ -362,8 +362,10 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, } t = tm; /* else repeat assignment over 'tm' */ luaV_fastset(t, key, val, hres, luaH_pset); - if (hres == HOK) + if (hres == HOK) { + luaV_finishfastset(L, t, val); return; /* done */ + } /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ } luaG_runerror(L, "'__newindex' chain too long; possible loop"); diff --git a/testes/gc.lua b/testes/gc.lua index 96eadad8..0693837c 100644 --- a/testes/gc.lua +++ b/testes/gc.lua @@ -600,6 +600,21 @@ if T then end +if T then + collectgarbage("stop") + T.gcstate("pause") + local sup = {x = 0} + local a = setmetatable({}, {__newindex = sup}) + T.gcstate("enteratomic") + assert(T.gccolor(sup) == "black") + a.x = {} -- should not break the invariant + assert(not (T.gccolor(sup) == "black" and T.gccolor(sup.x) == "white")) + T.gcstate("pause") -- complete the GC cycle + sup.x.y = 10 + collectgarbage("restart") +end + + if T then print("emergency collections") collectgarbage() -- cgit v1.2.3-55-g6feb