From 029d269f4d1afd0e9ea0f889eb3e65a7f0fab0f9 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 31 Aug 2017 13:14:41 -0300 Subject: bug: dead keys with nil values can stay in weak tables --- lgc.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'lgc.c') diff --git a/lgc.c b/lgc.c index c39850a4..e658a6f8 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.232 2017/06/12 14:21:44 roberto Exp roberto $ +** $Id: lgc.c,v 2.233 2017/06/29 15:06:44 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -117,7 +117,8 @@ static lu_mem atomic (lua_State *L); /* -** If key is not marked, mark its entry as dead. This allows the +** Clear keys for empty entries in tables. If entry is empty +** and its key is not marked, mark its entry as dead. This allows the ** collection of the key, but keeps its entry in the table (its removal ** could break a chain). Other places never manipulate dead keys, ** because its associated nil value is enough to signal that the entry @@ -688,10 +689,10 @@ static void clearkeys (global_State *g, GCObject *l) { Table *h = gco2t(l); Node *n, *limit = gnodelast(h); for (n = gnode(h, 0); n < limit; n++) { - if (!ttisnil(gval(n)) && (iscleared(g, gckeyN(n)))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* and remove entry from table */ - } + if (!ttisnil(gval(n)) && (iscleared(g, gckeyN(n)))) /* unmarked key? */ + setnilvalue(gval(n)); /* clear value */ + if (ttisnil(gval(n))) /* is entry empty? */ + removeentry(n); /* remove it from table */ } } } @@ -712,10 +713,10 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) { setnilvalue(o); /* remove value */ } for (n = gnode(h, 0); n < limit; n++) { - if (iscleared(g, gcvalueN(gval(n)))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* and remove entry from table */ - } + if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */ + setnilvalue(gval(n)); /* clear value */ + if (ttisnil(gval(n))) /* is entry empty? */ + removeentry(n); /* remove it from table */ } } } -- cgit v1.2.3-55-g6feb