I've finally got some time to debug that, and it is a real bug!
The core of the test case goes like this:
local parent = {}
parent.__newindex = parent
[...]
child = setmetatable({},parent)
child.fo_nt = {} --<< problem starts here
As 'child' doesn´t have that key, the metatable is invoked through
luaV_finishset. In the end of luaV_finishset, it needs to insert
the key into the __newindex table. In the example, that table is the
original table itself ('parent').
When it goes to insert key "fo_nt" into the 'parent' table, there is a
collision with "__newindex", and that previous entry (with the table
being updated) is moved to another place. Then, luaV_finishset proceeds
to check the barrier of the table (through 'luaV_finishfastset'), but
then the value 't' (which pointed to the "__newindex" entry) has already
another value, and so the barrier isn't called correctly, and so in the
next GC that new table (which now lives in parent.fo_nt) gets collected.
Sergey, was this bug found by OSS-Fuzz?
-- Roberto