summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaurnimator <quae@daurnimator.com>2017-05-22 16:24:46 +1000
committerdaurnimator <quae@daurnimator.com>2017-05-22 16:24:46 +1000
commit13ba814ab51f43718c1f07680012e6ee7815b16b (patch)
tree68e1e3fe1a00d5b0235b7aa0d543cc14506d3367
parentedf9e47120f2098458519628335a7e90b2569b70 (diff)
downloadfengari-13ba814ab51f43718c1f07680012e6ee7815b16b.tar.gz
fengari-13ba814ab51f43718c1f07680012e6ee7815b16b.tar.bz2
fengari-13ba814ab51f43718c1f07680012e6ee7815b16b.zip
Checks for nil and NaN table keys
-rw-r--r--src/lapi.js12
-rw-r--r--src/lcode.js2
-rw-r--r--src/llex.js2
-rw-r--r--src/ltable.js25
-rw-r--r--src/lvm.js6
5 files changed, 26 insertions, 21 deletions
diff --git a/src/lapi.js b/src/lapi.js
index 9aacb10..cea0568 100644
--- a/src/lapi.js
+++ b/src/lapi.js
@@ -419,9 +419,9 @@ const lua_rawset = function(L, idx) {
let k = L.stack[L.top - 2];
let v = L.stack[L.top - 1];
if (v.ttisnil()) {
- ltable.luaH_delete(o.value, k);
+ ltable.luaH_delete(L, o.value, k);
} else {
- let slot = ltable.luaH_set(o.value, k);
+ let slot = ltable.luaH_set(L, o.value, k);
slot.setfrom(v);
}
ltable.invalidateTMcache(o.value);
@@ -443,9 +443,9 @@ const lua_rawsetp = function(L, idx, p) {
let k = new TValue(CT.LUA_TLIGHTUSERDATA, p);
let v = L.stack[L.top - 1];
if (v.ttisnil()) {
- ltable.luaH_delete(o.value, k);
+ ltable.luaH_delete(L, o.value, k);
} else {
- let slot = ltable.luaH_set(o.value, k);
+ let slot = ltable.luaH_set(L, o.value, k);
slot.setfrom(v);
}
L.top--;
@@ -482,7 +482,7 @@ const lua_rawgetp = function(L, idx, p) {
let t = index2addr(L, idx);
assert(t.ttistable(), "table expected");
let k = new TValue(CT.LUA_TLIGHTUSERDATA, p);
- L.stack[L.top++] = ltable.luaH_get(t.value, k);
+ L.stack[L.top++] = ltable.luaH_get(L, t.value, k);
assert(L.top <= L.ci.top, "stack overflow");
return L.stack[L.top - 1].ttnov();
};
@@ -492,7 +492,7 @@ const lua_rawget = function(L, idx) {
assert(t.ttistable(t), "table expected");
- L.stack[L.top - 1] = ltable.luaH_get(t.value, L.stack[L.top - 1]);
+ L.stack[L.top - 1] = ltable.luaH_get(L, t.value, L.stack[L.top - 1]);
return L.stack[L.top - 1].ttnov();
};
diff --git a/src/lcode.js b/src/lcode.js
index 8f964d7..6515d93 100644
--- a/src/lcode.js
+++ b/src/lcode.js
@@ -439,7 +439,7 @@ const freeexps = function(fs, e1, e2) {
*/
const addk = function(fs, key, v) {
let f = fs.f;
- let idx = ltable.luaH_set(fs.ls.h, key); /* index scanner table */
+ let idx = ltable.luaH_set(fs.L, fs.ls.h, key); /* index scanner table */
if (idx.ttisinteger()) { /* is there an index there? */
let k = idx.value;
/* correct value? (warning: must distinguish floats from integers!) */
diff --git a/src/llex.js b/src/llex.js
index 998ab0e..5e6b9ec 100644
--- a/src/llex.js
+++ b/src/llex.js
@@ -147,7 +147,7 @@ const save_and_next = function(ls) {
const luaX_newstring = function(ls, str) {
let L = ls.L;
let ts = lstring.luaS_new(L, str);
- let o = ltable.luaH_set(ls.h, new lobject.TValue(defs.CT.LUA_TLNGSTR, ts));
+ let o = ltable.luaH_set(L, ls.h, new lobject.TValue(defs.CT.LUA_TLNGSTR, ts));
if (o.ttisnil()) { /* not in use yet? */
o.setbvalue(true);
} else { /* string already present */
diff --git a/src/ltable.js b/src/ltable.js
index 0ed56ab..c8bf7a2 100644
--- a/src/ltable.js
+++ b/src/ltable.js
@@ -9,11 +9,16 @@ const lobject = require('./lobject.js');
const lstring = require('./lstring.js');
const CT = defs.constant_types;
-const table_hash = function(key) {
+const table_hash = function(L, key) {
switch(key.type) {
+ case CT.LUA_TNIL:
+ return ldebug.luaG_runerror(L, defs.to_luastring("table index is nil", true));
+ case CT.LUA_TNUMFLT:
+ if (isNaN(key.value))
+ return ldebug.luaG_runerror(L, defs.to_luastring("table index is NaN", true));
+ /* fall through */
case CT.LUA_TBOOLEAN:
case CT.LUA_TLIGHTUSERDATA: /* XXX: if user pushes conflicting lightuserdata then the table will do odd things */
- case CT.LUA_TNUMFLT:
case CT.LUA_TNUMINT:
case CT.LUA_TTABLE:
case CT.LUA_TLCL:
@@ -110,11 +115,11 @@ const luaH_getstr = function(t, key) {
return getgeneric(t, lstring.luaS_hashlongstr(key));
};
-const luaH_get = function(t, key) {
+const luaH_get = function(L, t, key) {
assert(key instanceof lobject.TValue);
- if (key.ttisnil())
+ if (key.ttisnil() || (key.ttisfloat() && isNaN(key.value)))
return lobject.luaO_nilobject;
- return getgeneric(t, table_hash(key));
+ return getgeneric(t, table_hash(L, key));
};
const setgeneric = function(t, hash, key) {
@@ -145,15 +150,15 @@ const luaH_setint = function(t, key, value) {
}
};
-const luaH_set = function(t, key) {
+const luaH_set = function(L, t, key) {
assert(key instanceof lobject.TValue);
- let hash = table_hash(key);
+ let hash = table_hash(L, key);
return setgeneric(t, hash, new lobject.TValue(key.type, key.value));
};
-const luaH_delete = function(t, key) {
+const luaH_delete = function(L, t, key) {
assert(key instanceof lobject.TValue);
- let hash = table_hash(key);
+ let hash = table_hash(L, key);
return mark_dead(t, hash);
};
@@ -183,7 +188,7 @@ const luaH_next = function(L, table, keyI) {
return false;
} else {
/* First find current key */
- let hash = table_hash(keyO);
+ let hash = table_hash(L, keyO);
/* Look in main part of table */
entry = table.strong.get(hash);
if (entry) {
diff --git a/src/lvm.js b/src/lvm.js
index a5b10e0..6e1012c 100644
--- a/src/lvm.js
+++ b/src/lvm.js
@@ -1026,7 +1026,7 @@ const gettable = function(L, t, key, ra) {
ldebug.luaG_typeerror(L, t, defs.to_luastring('index', true)); /* no metamethod */
/* else will try the metamethod */
} else {
- let slot = ltable.luaH_get(t.value, key);
+ let slot = ltable.luaH_get(L, t.value, key);
if (!slot.ttisnil()) {
L.stack[ra] = new lobject.TValue(slot.type, slot.value);
return;
@@ -1054,10 +1054,10 @@ const settable = function(L, t, key, val) {
let tm;
if (t.ttistable()) {
let h = t.value; /* save 't' table */
- let slot = ltable.luaH_set(h, key);
+ let slot = ltable.luaH_set(L, h, key);
if (!slot.ttisnil() || (tm = ltm.fasttm(L, h.metatable, ltm.TMS.TM_NEWINDEX)) === null) {
if (val.ttisnil())
- ltable.luaH_delete(h, key);
+ ltable.luaH_delete(L, h, key);
else
slot.setfrom(val);
ltable.invalidateTMcache(h);