summaryrefslogtreecommitdiff
path: root/libs/liblua/src/ltable.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/liblua/src/ltable.c')
-rw-r--r--libs/liblua/src/ltable.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/libs/liblua/src/ltable.c b/libs/liblua/src/ltable.c
index 5a0d066faa..7e7cbed97c 100644
--- a/libs/liblua/src/ltable.c
+++ b/libs/liblua/src/ltable.c
@@ -166,17 +166,30 @@ static Node *mainpositionTV (const Table *t, const TValue *key) {
/*
-** Check whether key 'k1' is equal to the key in node 'n2'.
-** This equality is raw, so there are no metamethods. Floats
-** with integer values have been normalized, so integers cannot
-** be equal to floats. It is assumed that 'eqshrstr' is simply
-** pointer equality, so that short strings are handled in the
-** default case.
-*/
-static int equalkey (const TValue *k1, const Node *n2) {
- if (rawtt(k1) != keytt(n2)) /* not the same variants? */
+** Check whether key 'k1' is equal to the key in node 'n2'. This
+** equality is raw, so there are no metamethods. Floats with integer
+** values have been normalized, so integers cannot be equal to
+** floats. It is assumed that 'eqshrstr' is simply pointer equality, so
+** that short strings are handled in the default case.
+** A true 'deadok' means to accept dead keys as equal to their original
+** values. All dead keys are compared in the default case, by pointer
+** identity. (Only collectable objects can produce dead keys.) Note that
+** dead long strings are also compared by identity.
+** Once a key is dead, its corresponding value may be collected, and
+** then another value can be created with the same address. If this
+** other value is given to 'next', 'equalkey' will signal a false
+** positive. In a regular traversal, this situation should never happen,
+** as all keys given to 'next' came from the table itself, and therefore
+** could not have been collected. Outside a regular traversal, we
+** have garbage in, garbage out. What is relevant is that this false
+** positive does not break anything. (In particular, 'next' will return
+** some other valid item on the table or nil.)
+*/
+static int equalkey (const TValue *k1, const Node *n2, int deadok) {
+ if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */
+ !(deadok && keyisdead(n2) && iscollectable(k1)))
return 0; /* cannot be same key */
- switch (ttypetag(k1)) {
+ switch (keytt(n2)) {
case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE:
return 1;
case LUA_VNUMINT:
@@ -187,7 +200,7 @@ static int equalkey (const TValue *k1, const Node *n2) {
return pvalue(k1) == pvalueraw(keyval(n2));
case LUA_VLCF:
return fvalue(k1) == fvalueraw(keyval(n2));
- case LUA_VLNGSTR:
+ case ctb(LUA_VLNGSTR):
return luaS_eqlngstr(tsvalue(k1), keystrval(n2));
default:
return gcvalue(k1) == gcvalueraw(keyval(n2));
@@ -251,11 +264,12 @@ static unsigned int setlimittosize (Table *t) {
/*
** "Generic" get version. (Not that generic: not valid for integers,
** which may be in array part, nor for floats with integral values.)
+** See explanation about 'deadok' in function 'equalkey'.
*/
-static const TValue *getgeneric (Table *t, const TValue *key) {
+static const TValue *getgeneric (Table *t, const TValue *key, int deadok) {
Node *n = mainpositionTV(t, key);
for (;;) { /* check whether 'key' is somewhere in the chain */
- if (equalkey(key, n))
+ if (equalkey(key, n, deadok))
return gval(n); /* that's it */
else {
int nx = gnext(n);
@@ -292,7 +306,7 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key,
if (i - 1u < asize) /* is 'key' inside array part? */
return i; /* yes; that's the index */
else {
- const TValue *n = getgeneric(t, key);
+ const TValue *n = getgeneric(t, key, 1);
if (unlikely(isabstkey(n)))
luaG_runerror(L, "invalid key to 'next'"); /* key not found */
i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */
@@ -730,7 +744,7 @@ const TValue *luaH_getstr (Table *t, TString *key) {
else { /* for long strings, use generic case */
TValue ko;
setsvalue(cast(lua_State *, NULL), &ko, key);
- return getgeneric(t, &ko);
+ return getgeneric(t, &ko, 0);
}
}
@@ -750,7 +764,7 @@ const TValue *luaH_get (Table *t, const TValue *key) {
/* else... */
} /* FALLTHROUGH */
default:
- return getgeneric(t, key);
+ return getgeneric(t, key, 0);
}
}