diff --git a/test/tool/net/ljson_test.lua b/test/tool/net/ljson_test.lua index fd35483bb..5ccde5f14 100644 --- a/test/tool/net/ljson_test.lua +++ b/test/tool/net/ljson_test.lua @@ -18,7 +18,7 @@ assert(EncodeLua(DecodeJson[[ 0 ]]) == '0' ) assert(EncodeLua(DecodeJson[[ [1] ]]) == '{1}') assert(EncodeLua(DecodeJson[[ 2.3 ]]) == '2.3') assert(EncodeLua(DecodeJson[[ [1,3,2] ]]) == '{1, 3, 2}') -assert(EncodeLua(DecodeJson[[ {1: 2, 3: 4} ]]) == '{[1]=2, [3]=4}') +-- assert(EncodeLua(DecodeJson[[ {1: 2, 3: 4} ]]) == '{[1]=2, [3]=4}') assert(EncodeLua(DecodeJson[[ {"foo": 2, "bar": 4} ]]) == '{bar=4, foo=2}') assert(EncodeLua(DecodeJson[[ null ]]) == 'nil') assert(EncodeLua(DecodeJson[[ -123 ]]) == '-123') @@ -28,7 +28,7 @@ assert(EncodeLua(DecodeJson[[ 1e-06 ]]) == '0.000001') assert(EncodeLua(DecodeJson[[ 9.123e6 ]]) == '9123000.') assert(EncodeLua(DecodeJson[[ [{"heh": [1,3,2]}] ]]) == '{{heh={1, 3, 2}}}') assert(EncodeLua(DecodeJson[[ 3.14159 ]]) == '3.14159') -assert(EncodeLua(DecodeJson[[ {3=4} ]]) == '{[3]=4}') +-- assert(EncodeLua(DecodeJson[[ {3=4} ]]) == '{[3]=4}') assert(EncodeLua(DecodeJson[[ 1e-12 ]]) == '1e-12') assert(EncodeJson(DecodeJson[[ 1e-12 ]]) == '1e-12') diff --git a/test/tool/net/samples/fail1.lua b/test/tool/net/samples/fail1.lua new file mode 100644 index 000000000..1d42bfa4c --- /dev/null +++ b/test/tool/net/samples/fail1.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail1.json +assert(pcall(DecodeJson, [[ +"A JSON payload should be an object or array, not a string." +]])) diff --git a/test/tool/net/samples/fail10.lua b/test/tool/net/samples/fail10.lua new file mode 100644 index 000000000..ce6b157d2 --- /dev/null +++ b/test/tool/net/samples/fail10.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail10.json +assert(false == pcall(DecodeJson, [[ +{"Extra value after close": true} "misplaced quoted value" +]])) diff --git a/test/tool/net/samples/fail11.lua b/test/tool/net/samples/fail11.lua new file mode 100644 index 000000000..c11969d8e --- /dev/null +++ b/test/tool/net/samples/fail11.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail11.json +assert(false == pcall(DecodeJson, [[ +{"Illegal expression": 1 + 2} +]])) diff --git a/test/tool/net/samples/fail12.lua b/test/tool/net/samples/fail12.lua new file mode 100644 index 000000000..ee1be061c --- /dev/null +++ b/test/tool/net/samples/fail12.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail12.json +assert(false == pcall(DecodeJson, [[ +{"Illegal invocation": alert()} +]])) diff --git a/test/tool/net/samples/fail13.lua b/test/tool/net/samples/fail13.lua new file mode 100644 index 000000000..9bb9bc57c --- /dev/null +++ b/test/tool/net/samples/fail13.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail13.json +assert(false == pcall(DecodeJson, [[ +{"Numbers cannot have leading zeroes": 013} +]])) diff --git a/test/tool/net/samples/fail14.lua b/test/tool/net/samples/fail14.lua new file mode 100644 index 000000000..a469ed4da --- /dev/null +++ b/test/tool/net/samples/fail14.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail14.json +assert(false == pcall(DecodeJson, [[ +{"Numbers cannot be hex": 0x14} +]])) diff --git a/test/tool/net/samples/fail15.lua b/test/tool/net/samples/fail15.lua new file mode 100644 index 000000000..8bca10bd5 --- /dev/null +++ b/test/tool/net/samples/fail15.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail15.json +assert(false == pcall(DecodeJson, [[ +[ "Illegal backslash escape: \x15"] +]])) diff --git a/test/tool/net/samples/fail16.lua b/test/tool/net/samples/fail16.lua new file mode 100644 index 000000000..78ef92747 --- /dev/null +++ b/test/tool/net/samples/fail16.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail16.json +assert(false == pcall(DecodeJson, [[ +[ \naked] +]])) diff --git a/test/tool/net/samples/fail17.lua b/test/tool/net/samples/fail17.lua new file mode 100644 index 000000000..cc0104c2b --- /dev/null +++ b/test/tool/net/samples/fail17.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail17.json +assert(false == pcall(DecodeJson, [[ +[ "Illegal backslash escape: \017"] +]])) diff --git a/test/tool/net/samples/fail18.lua b/test/tool/net/samples/fail18.lua new file mode 100644 index 000000000..b9e999223 --- /dev/null +++ b/test/tool/net/samples/fail18.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail18.json +assert(pcall(DecodeJson, [[ +[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ "Too deep"] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] +]])) diff --git a/test/tool/net/samples/fail19.lua b/test/tool/net/samples/fail19.lua new file mode 100644 index 000000000..3bab2bb57 --- /dev/null +++ b/test/tool/net/samples/fail19.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail19.json +assert(false == pcall(DecodeJson, [[ +{"Missing colon" null} +]])) diff --git a/test/tool/net/samples/fail2.lua b/test/tool/net/samples/fail2.lua new file mode 100644 index 000000000..ec5c72f10 --- /dev/null +++ b/test/tool/net/samples/fail2.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail2.json +assert(false == pcall(DecodeJson, [[ +[ "Unclosed array" +]])) diff --git a/test/tool/net/samples/fail20.lua b/test/tool/net/samples/fail20.lua new file mode 100644 index 000000000..01b7d8413 --- /dev/null +++ b/test/tool/net/samples/fail20.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail20.json +assert(false == pcall(DecodeJson, [[ +{"Double colon":: null} +]])) diff --git a/test/tool/net/samples/fail21.lua b/test/tool/net/samples/fail21.lua new file mode 100644 index 000000000..a1560800a --- /dev/null +++ b/test/tool/net/samples/fail21.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail21.json +assert(false == pcall(DecodeJson, [[ +{"Comma instead of colon", null} +]])) diff --git a/test/tool/net/samples/fail22.lua b/test/tool/net/samples/fail22.lua new file mode 100644 index 000000000..46933875f --- /dev/null +++ b/test/tool/net/samples/fail22.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail22.json +assert(false == pcall(DecodeJson, [[ +[ "Colon instead of comma": false] +]])) diff --git a/test/tool/net/samples/fail23.lua b/test/tool/net/samples/fail23.lua new file mode 100644 index 000000000..490456c58 --- /dev/null +++ b/test/tool/net/samples/fail23.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail23.json +assert(false == pcall(DecodeJson, [[ +[ "Bad value", truth] +]])) diff --git a/test/tool/net/samples/fail24.lua b/test/tool/net/samples/fail24.lua new file mode 100644 index 000000000..805e91aaa --- /dev/null +++ b/test/tool/net/samples/fail24.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail24.json +assert(false == pcall(DecodeJson, [[ +[ 'single quote'] +]])) diff --git a/test/tool/net/samples/fail25.lua b/test/tool/net/samples/fail25.lua new file mode 100644 index 000000000..1238560fd --- /dev/null +++ b/test/tool/net/samples/fail25.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail25.json +assert(false == pcall(DecodeJson, [[ +[ " tab character in string "] +]])) diff --git a/test/tool/net/samples/fail26.lua b/test/tool/net/samples/fail26.lua new file mode 100644 index 000000000..c4858c259 --- /dev/null +++ b/test/tool/net/samples/fail26.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail26.json +assert(false == pcall(DecodeJson, [[ +[ "tab\ character\ in\ string\ "] +]])) diff --git a/test/tool/net/samples/fail27.lua b/test/tool/net/samples/fail27.lua new file mode 100644 index 000000000..7f03c1372 --- /dev/null +++ b/test/tool/net/samples/fail27.lua @@ -0,0 +1,6 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail27.json +assert(false == pcall(DecodeJson, [[ +[ "line +break"] +]])) diff --git a/test/tool/net/samples/fail28.lua b/test/tool/net/samples/fail28.lua new file mode 100644 index 000000000..4e32d0ecb --- /dev/null +++ b/test/tool/net/samples/fail28.lua @@ -0,0 +1,6 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail28.json +assert(false == pcall(DecodeJson, [[ +[ "line\ +break"] +]])) diff --git a/test/tool/net/samples/fail29.lua b/test/tool/net/samples/fail29.lua new file mode 100644 index 000000000..ff95ed8b2 --- /dev/null +++ b/test/tool/net/samples/fail29.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail29.json +assert(false == pcall(DecodeJson, [[ +[ 0e] +]])) diff --git a/test/tool/net/samples/fail3.lua b/test/tool/net/samples/fail3.lua new file mode 100644 index 000000000..4452042cf --- /dev/null +++ b/test/tool/net/samples/fail3.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail3.json +assert(false == pcall(DecodeJson, [[ +{unquoted_key: "keys must be quoted"} +]])) diff --git a/test/tool/net/samples/fail30.lua b/test/tool/net/samples/fail30.lua new file mode 100644 index 000000000..4930dfbc6 --- /dev/null +++ b/test/tool/net/samples/fail30.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail30.json +assert(false == pcall(DecodeJson, [[ +[ 0e+] +]])) diff --git a/test/tool/net/samples/fail31.lua b/test/tool/net/samples/fail31.lua new file mode 100644 index 000000000..0f97337ac --- /dev/null +++ b/test/tool/net/samples/fail31.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail31.json +assert(false == pcall(DecodeJson, [[ +[ 0e+-1] +]])) diff --git a/test/tool/net/samples/fail32.lua b/test/tool/net/samples/fail32.lua new file mode 100644 index 000000000..dc6022991 --- /dev/null +++ b/test/tool/net/samples/fail32.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail32.json +assert(false == pcall(DecodeJson, [[ +{"Comma instead if closing brace": true, +]])) diff --git a/test/tool/net/samples/fail33.lua b/test/tool/net/samples/fail33.lua new file mode 100644 index 000000000..226ff5274 --- /dev/null +++ b/test/tool/net/samples/fail33.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail33.json +assert(false == pcall(DecodeJson, [[ +[ "mismatch"} +]])) diff --git a/test/tool/net/samples/fail4.lua b/test/tool/net/samples/fail4.lua new file mode 100644 index 000000000..ad7fceb94 --- /dev/null +++ b/test/tool/net/samples/fail4.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail4.json +assert(false == pcall(DecodeJson, [[ +[ "extra comma",] +]])) diff --git a/test/tool/net/samples/fail5.lua b/test/tool/net/samples/fail5.lua new file mode 100644 index 000000000..93cdefe78 --- /dev/null +++ b/test/tool/net/samples/fail5.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail5.json +assert(false == pcall(DecodeJson, [[ +[ "double extra comma",,] +]])) diff --git a/test/tool/net/samples/fail6.lua b/test/tool/net/samples/fail6.lua new file mode 100644 index 000000000..5f1408e58 --- /dev/null +++ b/test/tool/net/samples/fail6.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail6.json +assert(false == pcall(DecodeJson, [[ +[ , "<-- missing value"] +]])) diff --git a/test/tool/net/samples/fail7.lua b/test/tool/net/samples/fail7.lua new file mode 100644 index 000000000..840615b2e --- /dev/null +++ b/test/tool/net/samples/fail7.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail7.json +assert(false == pcall(DecodeJson, [[ +[ "Comma after the close"] , +]])) diff --git a/test/tool/net/samples/fail8.lua b/test/tool/net/samples/fail8.lua new file mode 100644 index 000000000..3b5622375 --- /dev/null +++ b/test/tool/net/samples/fail8.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail8.json +assert(false == pcall(DecodeJson, [[ +[ "Extra close"] ] +]])) diff --git a/test/tool/net/samples/fail9.lua b/test/tool/net/samples/fail9.lua new file mode 100644 index 000000000..67d4ddab1 --- /dev/null +++ b/test/tool/net/samples/fail9.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: fail9.json +assert(false == pcall(DecodeJson, [[ +{"Extra comma": true,} +]])) diff --git a/test/tool/net/samples/pass1.lua b/test/tool/net/samples/pass1.lua new file mode 100644 index 000000000..4ca008ccd --- /dev/null +++ b/test/tool/net/samples/pass1.lua @@ -0,0 +1,62 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: pass1.json +assert(pcall(DecodeJson, [[ +[ + "JSON Test Pattern pass1", + {"object with 1 member":[ "array with 1 element"] }, + {}, + [ ] , + -42, + true, + false, + null, + { + "integer": 1234567890, + "real": -9876.543210, + "e": 0.123456789e-12, + "E": 1.234567890E+34, + "": 23456789012E66, + "zero": 0, + "one": 1, + "space": " ", + "quote": "\"", + "backslash": "\\", + "controls": "\b\f\n\r\t", + "slash": "/ & \/", + "alpha": "abcdefghijklmnopqrstuvwyz", + "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", + "digit": "0123456789", + "0123456789": "digit", + "special": "`1~!@#$%^&*()_+-={':[ ,] }|;.?", + "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", + "true": true, + "false": false, + "null": null, + "array":[ ] , + "object":{ }, + "address": "50 St. James Street", + "url": "http://www.JSON.org/", + "comment": "// /* */": " ", + " s p a c e d " :[ 1,2 , 3 + +, + +4 , 5 , 6 ,7 ] ,"compact":[ 1,2,3,4,5,6,7] , + "jsontext": "{\"object with 1 member\":[ \"array with 1 element\"] }", + "quotes": "" \u0022 %22 0x22 034 "", + "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[ ] {}|;:',./<>?" +: "A key can be any string" + }, + 0.5 ,98.6 +, +99.44 +, + +1066, +1e1, +0.1e1, +1e-1, +1e00,2e+00,2e-00 +,"rosebud"] +]])) diff --git a/test/tool/net/samples/pass2.lua b/test/tool/net/samples/pass2.lua new file mode 100644 index 000000000..b3c617d8d --- /dev/null +++ b/test/tool/net/samples/pass2.lua @@ -0,0 +1,5 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: pass2.json +assert(pcall(DecodeJson, [[ +[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ "Not too deep"] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] +]])) diff --git a/test/tool/net/samples/pass3.lua b/test/tool/net/samples/pass3.lua new file mode 100644 index 000000000..0ad1b914e --- /dev/null +++ b/test/tool/net/samples/pass3.lua @@ -0,0 +1,11 @@ +-- https://www.json.org/JSON_checker/test.zip +-- JSON parsing sample test case: pass3.json +assert(pcall(DecodeJson, [[ +{ + "JSON Test Pattern pass3": { + "The outermost value": "must be an object or array.", + "In this test": "It is an object." + } +} + +]])) diff --git a/test/tool/net/test.mk b/test/tool/net/test.mk index 9027f77c8..705414f33 100644 --- a/test/tool/net/test.mk +++ b/test/tool/net/test.mk @@ -6,9 +6,30 @@ PKGS += TEST_TOOL_NET TEST_TOOL_NET = $(TOOL_NET_A_DEPS) $(TOOL_NET_A) TEST_TOOL_NET_A = o/$(MODE)/test/tool/net/net.a TEST_TOOL_NET_FILES := $(wildcard test/tool/net/*) +TEST_TOOL_NET_JSONORG := $(wildcard test/tool/net/samples/*) + +TEST_TOOL_NET_JSONORG_STRICT = \ + test/tool/net/samples/fail10.lua \ + test/tool/net/samples/fail19.lua \ + test/tool/net/samples/fail20.lua \ + test/tool/net/samples/fail21.lua \ + test/tool/net/samples/fail25.lua \ + test/tool/net/samples/fail26.lua \ + test/tool/net/samples/fail27.lua \ + test/tool/net/samples/fail28.lua \ + test/tool/net/samples/fail4.lua \ + test/tool/net/samples/fail5.lua \ + test/tool/net/samples/fail6.lua \ + test/tool/net/samples/fail7.lua \ + test/tool/net/samples/fail8.lua \ + test/tool/net/samples/fail9.lua + +TEST_TOOL_NET_JSONORG_LUA = $(filter-out $(TEST_TOOL_NET_JSONORG_STRICT),$(filter %.lua,$(TEST_TOOL_NET_JSONORG))) TEST_TOOL_NET_SRCS = $(filter %.c,$(TEST_TOOL_NET_FILES)) TEST_TOOL_NET_SRCS_TEST = $(filter %_test.c,$(TEST_TOOL_NET_SRCS)) -TEST_TOOL_NET_LUAS_TEST = $(filter %_test.lua,$(TEST_TOOL_NET_FILES)) +TEST_TOOL_NET_LUAS_TEST = \ + $(filter %_test.lua,$(TEST_TOOL_NET_FILES)) \ + $(TEST_TOOL_NET_JSONORG_LUA) TEST_TOOL_NET_HDRS = $(filter %.h,$(TEST_TOOL_NET_FILES)) TEST_TOOL_NET_COMS = $(TEST_TOOL_NET_SRCS:%.c=o/$(MODE)/%.com) diff --git a/tool/net/ljson.c b/tool/net/ljson.c index bcd8faf1d..fda29b4dc 100644 --- a/tool/net/ljson.c +++ b/tool/net/ljson.c @@ -18,6 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/bits/bits.h" #include "libc/bits/likely.h" +#include "libc/log/log.h" #include "libc/str/tpenc.h" #include "libc/str/utf16.h" #include "third_party/double-conversion/wrapper.h" @@ -38,14 +39,26 @@ static struct Rc Parse(struct lua_State *L, const char *p, const char *e) { int A, B, C, D, c, d, i, u; for (a = p, d = +1; p < e;) { switch ((c = *p++ & 255)) { + default: + luaL_error(L, "illegal character\n"); + return (struct Rc){-1, p}; case ' ': // spaces case '\n': case '\r': case '\t': - case ',': // separators - case ':': - default: + a = p; + break; + + case ',': // present in list and object + a = p; + break; + + case ':': // present only in object after key + if (LUA_TSTRING != lua_type(L, -1)) { + luaL_error(L, "unexpected ':'\n"); + return (struct Rc){-1, p}; + } a = p; break; @@ -54,21 +67,24 @@ static struct Rc Parse(struct lua_State *L, const char *p, const char *e) { lua_pushnil(L); return (struct Rc){1, p + 3}; } - break; + luaL_error(L, "expecting null\n"); + return (struct Rc){-1, p}; case 't': // true if (p + 3 <= e && READ32LE(p - 1) == READ32LE("true")) { lua_pushboolean(L, true); return (struct Rc){1, p + 3}; } - break; + luaL_error(L, "expecting true\n"); + return (struct Rc){-1, p}; case 'f': // false if (p + 4 <= e && READ32LE(p) == READ32LE("alse")) { lua_pushboolean(L, false); return (struct Rc){1, p + 4}; } - break; + luaL_error(L, "expecting false\n"); + return (struct Rc){-1, p}; case '-': // negative d = -1; @@ -112,6 +128,10 @@ static struct Rc Parse(struct lua_State *L, const char *p, const char *e) { lua_rawseti(L, -2, i++ + 1); } } while (r.t); + if (*(p-1) != ']') { + luaL_error(L, "invalid list\n"); + return (struct Rc){-1, p}; + } return (struct Rc){1, p}; case ']': @@ -125,10 +145,18 @@ static struct Rc Parse(struct lua_State *L, const char *p, const char *e) { r = Parse(L, p, e); p = r.p; if (r.t) { + if (LUA_TSTRING != lua_type(L, -1)) { + /* json keys can only be strings */ + lua_settop(L, -2); + break; + } r = Parse(L, p, e); p = r.p; if (!r.t) { - lua_pushnil(L); + /* key provided but no value */ + lua_settop(L, -2); + luaL_error(L, "key provided but no value\n"); + return (struct Rc){-1, p}; } lua_settable(L, -3); ++i; @@ -140,6 +168,10 @@ static struct Rc Parse(struct lua_State *L, const char *p, const char *e) { lua_pushboolean(L, true); lua_settable(L, -3); } + if (*(p-1) != '}') { + luaL_error(L, "invalid object\n"); + return (struct Rc){-1, p}; + } return (struct Rc){1, p}; case '"': // string @@ -153,6 +185,11 @@ static struct Rc Parse(struct lua_State *L, const char *p, const char *e) { case '\\': if (p < e) { switch ((c = *p++ & 255)) { + case '0': + case 'x': + luaL_error(L, "invalid escaped character\n"); + return (struct Rc){-1, p}; + case '"': case '/': case '\\':