[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Heap overflow in luaH_get
- From: Roberto Ierusalimschy <roberto@...>
- Date: Thu, 9 Jul 2020 12:07:12 -0300
> > The generational GC code seems to be assuming that a G_OLD1 object must
> > be somewhere between g->survival and g->reallyold, or between g->finobj
> > and g->finobjrold.
> >
> > But what happens in this case is that some table with an age of OLD1 has
> > a metatable with a __gc metamethod, and when GCTM is being called for
> > it, it gets moved back to the allgc list _at the front_, while remaining
> > G_OLD1 (this is in udata2finalize).
> >
> > But since the table is not between g->survival and g->reallyold, and
> > nevertheless is only OLD1 (and its metatable is at this point only
> > SURVIVAL and white), it's not being processed by markold. Also, at some
> > point in correctgraylist, the table was changed from grey to black while
> > its metatable remained white. This results in the metatable being freed
> > before the object that references it, hence the later crash.
>
> Exactly! I guess the correction is moving its age back to OLD0, but
> I have to check that. Similar problems should occurr with other ages.
>
> Usually, an object's metatable is set right after its creation,
> so the object is still new and everything works fine. In the
> crashing code, the «setmetatable({}, ...)» looks like the metable
> is being set right after the «{}», but the code to create the
> metatable is long and slow, aging the table.
I think we have a dual problem in luaC_checkfinalizer, when we move
the object from the allgc list to the finobj list. Again, it must
go into the beginning of the list (to keep the order right), but
it may have the wrong age to go there.
-- Roberto