From 13ba814ab51f43718c1f07680012e6ee7815b16b Mon Sep 17 00:00:00 2001 From: daurnimator Date: Mon, 22 May 2017 16:24:46 +1000 Subject: Checks for nil and NaN table keys --- src/lapi.js | 12 ++++++------ src/lcode.js | 2 +- src/llex.js | 2 +- src/ltable.js | 25 +++++++++++++++---------- src/lvm.js | 6 +++--- 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); -- cgit v1.2.3-70-g09d2