Audit every single JSON test

This commit is contained in:
Justine Tunney 2022-07-12 12:30:42 -07:00
parent 7965ed0232
commit 3f3e7e92d7
17 changed files with 473 additions and 285 deletions

View file

@ -23,7 +23,7 @@
#include "net/http/escape.h" #include "net/http/escape.h"
/** /**
* Filters out control codes from string. * Makes control codes and trojan source plainly viewable.
* *
* This is useful for logging data like HTTP messages, where we don't * This is useful for logging data like HTTP messages, where we don't
* want full blown C string literal escaping, but we don't want things * want full blown C string literal escaping, but we don't want things
@ -67,6 +67,32 @@ char *VisualizeControlCodes(const char *data, size_t size, size_t *out_size) {
} }
} }
} }
// remap trojan source characters
if (x == 0x2028) {
x = L''; // line separator
} else if (x == 0x2029) {
x = L''; // paragraph separator
} else if (x == 0x202A) {
x = L''; // left-to-right embedding
} else if (x == 0x202B) {
x = L''; // right-to-left embedding
} else if (x == 0x202D) {
x = L''; // left-to-right override
} else if (x == 0x202E) {
x = L''; // right-to-left override
} else if (x == 0x2066) {
x = L''; // left-to-right isolate
} else if (x == 0x2067) {
x = L''; // right-to-left isolate
} else if (x == 0x2068) {
x = L''; // first strong isolate
} else if (x == 0x202C) {
x = L''; // pop directional formatting
} else if (x == 0x2069) {
x = L''; // pop directional isolate
}
if (0x80 <= x && x < 0xA0) { if (0x80 <= x && x < 0xA0) {
q[0] = '\\'; q[0] = '\\';
q[1] = 'u'; q[1] = 'u';

View file

@ -85,7 +85,6 @@ assert(err == "won't serialize cyclic lua table")
-- pass the parser to itself lool -- pass the parser to itself lool
json, err = EncodeJson(EncodeJson) json, err = EncodeJson(EncodeJson)
assert(not json) assert(not json)
print(err)
assert(err == "unsupported lua type") assert(err == "unsupported lua type")
-- EncodeJson() sorts table entries -- EncodeJson() sorts table entries
@ -145,6 +144,9 @@ assert(ParseHttpDateTime("Fri, 08 Jul 2022 16:17:43 GMT") == 1657297063)
assert(FormatHttpDateTime(1657297063) == "Fri, 08 Jul 2022 16:17:43 GMT") assert(FormatHttpDateTime(1657297063) == "Fri, 08 Jul 2022 16:17:43 GMT")
assert(VisualizeControlCodes("hello\x00") == "hello␀") assert(VisualizeControlCodes("hello\x00") == "hello␀")
assert(VisualizeControlCodes("\xe2\x80\xa8") == "") -- line separator
assert(VisualizeControlCodes("\xe2\x80\xaa") == "") -- left-to-right embedding
assert(VisualizeControlCodes("\xe2\x80\xab") == "") -- right-to-left embedding
assert(math.floor(10 * MeasureEntropy(" ") + .5) == 0) assert(math.floor(10 * MeasureEntropy(" ") + .5) == 0)
assert(math.floor(10 * MeasureEntropy("abcabcabcabc") + .5) == 16) assert(math.floor(10 * MeasureEntropy("abcabcabcabc") + .5) == 16)

View file

@ -17,7 +17,6 @@ assert(EncodeLua(assert(DecodeJson[[ 0 ]])) == '0' )
assert(EncodeLua(assert(DecodeJson[[ [1] ]])) == '{1}') assert(EncodeLua(assert(DecodeJson[[ [1] ]])) == '{1}')
assert(EncodeLua(assert(DecodeJson[[ 2.3 ]])) == '2.3') assert(EncodeLua(assert(DecodeJson[[ 2.3 ]])) == '2.3')
assert(EncodeLua(assert(DecodeJson[[ [1,3,2] ]])) == '{1, 3, 2}') assert(EncodeLua(assert(DecodeJson[[ [1,3,2] ]])) == '{1, 3, 2}')
-- assert(EncodeLua(assert(DecodeJson[[ {1: 2, 3: 4} ]])) == '{[1]=2, [3]=4}')
assert(EncodeLua(assert(DecodeJson[[ {"foo": 2, "bar": 4} ]])) == '{bar=4, foo=2}') assert(EncodeLua(assert(DecodeJson[[ {"foo": 2, "bar": 4} ]])) == '{bar=4, foo=2}')
assert(EncodeLua(assert(DecodeJson[[ -123 ]])) == '-123') assert(EncodeLua(assert(DecodeJson[[ -123 ]])) == '-123')
assert(EncodeLua(assert(DecodeJson[[ 1e6 ]])) == '1000000.') assert(EncodeLua(assert(DecodeJson[[ 1e6 ]])) == '1000000.')
@ -26,7 +25,6 @@ assert(EncodeLua(assert(DecodeJson[[ 1e-06 ]])) == '0.000001')
assert(EncodeLua(assert(DecodeJson[[ 9.123e6 ]])) == '9123000.') assert(EncodeLua(assert(DecodeJson[[ 9.123e6 ]])) == '9123000.')
assert(EncodeLua(assert(DecodeJson[[ [{"heh": [1,3,2]}] ]])) == '{{heh={1, 3, 2}}}') assert(EncodeLua(assert(DecodeJson[[ [{"heh": [1,3,2]}] ]])) == '{{heh={1, 3, 2}}}')
assert(EncodeLua(assert(DecodeJson[[ 3.14159 ]])) == '3.14159') assert(EncodeLua(assert(DecodeJson[[ 3.14159 ]])) == '3.14159')
-- assert(EncodeLua(assert(DecodeJson[[ {3=4} ]])) == '{[3]=4}')
assert(EncodeLua(assert(DecodeJson[[ 1e-12 ]])) == '1e-12') assert(EncodeLua(assert(DecodeJson[[ 1e-12 ]])) == '1e-12')
assert(EncodeJson(assert(DecodeJson[[ 1e-12 ]])) == '1e-12') assert(EncodeJson(assert(DecodeJson[[ 1e-12 ]])) == '1e-12')
@ -52,6 +50,14 @@ assert(EncodeJson(assert(DecodeJson[[ 9223372036854775807.0 ]])) == '9223372036
assert(EncodeJson(assert(DecodeJson[[ 2.7182818284590452354 ]])) == '2.718281828459045') -- euler constant w/ 17 digit precision assert(EncodeJson(assert(DecodeJson[[ 2.7182818284590452354 ]])) == '2.718281828459045') -- euler constant w/ 17 digit precision
assert( EncodeLua(assert(DecodeJson[[ 2.7182818284590452354 ]])) == '2.718281828459045') -- euler constant w/ 17 digit precision assert( EncodeLua(assert(DecodeJson[[ 2.7182818284590452354 ]])) == '2.718281828459045') -- euler constant w/ 17 digit precision
res, err = DecodeJson[[ null ]]
assert(res == nil)
assert(err == nil)
res, err = DecodeJson[[ false ]]
assert(res == false)
assert(err == nil)
res, err = DecodeJson[[ ]] res, err = DecodeJson[[ ]]
assert(not res) assert(not res)
assert(err == 'unexpected eof') assert(err == 'unexpected eof')
@ -60,14 +66,6 @@ res, err = DecodeJson[[ {} {} ]]
assert(not res) assert(not res)
assert(err == "junk after expression") assert(err == "junk after expression")
res, err = DecodeJson[[ null ]]
assert(not res)
assert(err == "toplevel json can't be null")
res, err = DecodeJson[[ false ]]
assert(not res)
assert(err == "toplevel json can't be false")
res, err = DecodeJson[[ {3:4} ]] res, err = DecodeJson[[ {3:4} ]]
assert(not res) assert(not res)
assert(err == "object key must be string") assert(err == "object key must be string")
@ -96,6 +94,26 @@ res, err = DecodeJson[[ {true:3} ]]
assert(not res) assert(not res)
assert(err == "object key must be string") assert(err == "object key must be string")
res, err = DecodeJson('"\x00"')
assert(res == nil)
assert(err == 'non-del c0 in string')
res, err = DecodeJson('"e')
assert(res == nil)
assert(err == 'unexpected eof in string')
res, err = DecodeJson('"\\xcc\\xa9"')
assert(res == nil)
assert(err == 'hex escape not printable')
res, err = DecodeJson('"\\xcj"')
assert(res == nil)
assert(err == 'invalid hex escape')
res, err = DecodeJson('"\\ucjcc"')
assert(res == nil)
assert(err == 'invalid unicode escape')
res, err = DecodeJson('[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[') res, err = DecodeJson('[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[')
assert(not res) assert(not res)
assert(err == "maximum depth exceeded") assert(err == "maximum depth exceeded")

View file

@ -236,8 +236,7 @@ assert(not DecodeJson(' ["x" '))
assert(not DecodeJson(' ["": 1] ')) assert(not DecodeJson(' ["": 1] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_a_invalid_utf8.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_a_invalid_utf8.json
-- (converted to binary for safety) assert(not DecodeJson(" [a\xe5] "))
assert(not DecodeJson(' \x5b\x61\xe5\x5d '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_comma_instead_of_colon.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_comma_instead_of_colon.json
assert(not DecodeJson(' {"x", null} ')) assert(not DecodeJson(' {"x", null} '))
@ -252,3 +251,21 @@ assert(not DecodeJson(' 123\x00 '))
-- (added spaces between [[ and ]] so lua doesn't get confused) -- (added spaces between [[ and ]] so lua doesn't get confused)
assert(not DecodeJson([[ assert(not DecodeJson([[
[ "x"] ] ]])) [ "x"] ] ]]))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_with_leading_zero.json
assert(not DecodeJson(' [012] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_neg_int_starting_with_zero.json
assert(not DecodeJson(' [-012] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_1_000.json
assert(not DecodeJson(' [1 000.0] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_-01.json
assert(not DecodeJson(' [-01] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_minus_space_1.json
assert(not DecodeJson(' [- 1] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_just_minus.json
assert(not DecodeJson(' [-] '))

View file

@ -26,7 +26,6 @@
-- SOFTWARE. -- SOFTWARE.
-- --
-- these test cases are prefixed with n_ -- these test cases are prefixed with n_
-- ljson should reject all of them as invalid -- ljson should reject all of them as invalid

View file

@ -1,4 +1,3 @@
-- --
-- Nicolas Seriot's JSONTestSuite -- Nicolas Seriot's JSONTestSuite
-- https://github.com/nst/JSONTestSuite -- https://github.com/nst/JSONTestSuite
@ -27,7 +26,6 @@
-- SOFTWARE. -- SOFTWARE.
-- --
-- these test cases are prefixed with n_ -- these test cases are prefixed with n_
-- ljson should reject all of them as invalid -- ljson should reject all of them as invalid

View file

@ -1,4 +1,3 @@
-- --
-- Nicolas Seriot's JSONTestSuite -- Nicolas Seriot's JSONTestSuite
-- https://github.com/nst/JSONTestSuite -- https://github.com/nst/JSONTestSuite
@ -31,48 +30,40 @@
-- ljson should reject all of them as invalid -- ljson should reject all of them as invalid
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_start_escape_unclosed.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_start_escape_unclosed.json
-- (converted to binary for safety) assert(not DecodeJson(" [\"\\ "))
assert(not DecodeJson(' \x5b\x22\x5c '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_single_string_no_double_quotes.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_single_string_no_double_quotes.json
-- (converted to binary for safety) assert(not DecodeJson(" abc "))
assert(not DecodeJson(' \x61\x62\x63 '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_single_quote.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_single_quote.json
-- (converted to binary for safety) assert(not DecodeJson(" [\'single quote\'] "))
assert(not DecodeJson(' \x5b\x27\x73\x69\x6e\x67\x6c\x65\x20\x71\x75\x6f\x74\x65\x27\x5d '))
-- disallow escape code outside string
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_no_quotes_with_bad_escape.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_no_quotes_with_bad_escape.json
-- (converted to binary for safety) assert(not DecodeJson(" [\\n] "))
assert(not DecodeJson(' \x5b\x5c\x6e\x5d '))
-- disallow unicode escape outside string
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_leading_uescaped_thinspace.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_leading_uescaped_thinspace.json
-- (converted to binary for safety) assert(not DecodeJson(" [\\u0020\"asd\"] "))
assert(not DecodeJson(' \x5b\x5c\x75\x30\x30\x32\x30\x22\x61\x73\x64\x22\x5d '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_incomplete_surrogate_escape_invalid.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_incomplete_surrogate_escape_invalid.json
-- (converted to binary for safety) assert(not DecodeJson(" [\"\\uD800\\uD800\\x\"] "))
assert(not DecodeJson(' \x5b\x22\x5c\x75\x44\x38\x30\x30\x5c\x75\x44\x38\x30\x30\x5c\x78\x22\x5d '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_incomplete_escape.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_incomplete_escape.json
-- (converted to binary for safety) assert(not DecodeJson(" [\"\\\"] "))
assert(not DecodeJson(' \x5b\x22\x5c\x22\x5d '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_escaped_backslash_bad.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_escaped_backslash_bad.json
-- (converted to binary for safety) assert(not DecodeJson(" [\"\\\\\\\"] "))
assert(not DecodeJson(' \x5b\x22\x5c\x5c\x5c\x22\x5d '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_accentuated_char_no_quotes.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_accentuated_char_no_quotes.json
-- (converted to binary for safety) assert(not DecodeJson(" [é] "))
assert(not DecodeJson(' \x5b\xc3\xa9\x5d ')) assert(DecodeJson(" [\"é\"] "))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_1_surrogate_then_escape.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_1_surrogate_then_escape.json
-- (converted to binary for safety) assert(not DecodeJson(" [\"\\uD800\\\"] "))
assert(not DecodeJson(' \x5b\x22\x5c\x75\x44\x38\x30\x30\x5c\x22\x5d '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_with_single_string.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_with_single_string.json
-- (converted to binary for safety) assert(not DecodeJson(" { \"foo\" : \"bar\", \"a\" } "))
assert(not DecodeJson(' \x7b\x20\x22\x66\x6f\x6f\x22\x20\x3a\x20\x22\x62\x61\x72\x22\x2c\x20\x22\x61\x22\x20\x7d '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_unterminated-value.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_unterminated-value.json
assert(not DecodeJson(' {"a":"a ')) assert(not DecodeJson(' {"a":"a '))
@ -174,3 +165,15 @@ assert(not DecodeJson(' {"a":"b"}/**// '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_trailing_comment.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_trailing_comment.json
assert(not DecodeJson(' {"a":"b"}/**/ ')) assert(not DecodeJson(' {"a":"b"}/**/ '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_unescaped_ctrl_char.json
assert(not DecodeJson(" [\"a\x00a\"] "))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_escape_x.json
assert(not DecodeJson(" [\"a\\x00a\"] "))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_unescaped_tab.json
assert(not DecodeJson(" [\"\t\"] "))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_unescaped_newline.json
assert(not DecodeJson(" [\"new\nline\"] "))

View file

@ -26,111 +26,111 @@
-- SOFTWARE. -- SOFTWARE.
-- --
-- [jart] these tests deviate from the expectations of the upstream test
-- suite. most of these failures are because we permit syntax
-- like this since it saves bandwidth and makes the impl smaller.
-- we're also more permissive about things like the encoding of
-- double exponents and empty double fraction.
assert(EncodeLua(DecodeJson('[0 1 2 3 4]')) == '{0, 1, 2, 3, 4}')
-- from fail4.lua -- from fail4.lua
--------------------------------------------------------------------------------
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_escape_x.json
-- (converted to binary for safety)
assert(DecodeJson(" [\"\\x00\"] "))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_unescaped_tab.json
-- (converted to binary for safety)
assert(DecodeJson([[ [" "] ]]))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_unescaped_newline.json
-- (converted to binary for safety)
assert(DecodeJson(" [\"new\nline\"] "))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_string_unescaped_ctrl_char.json
-- (converted to binary for safety)
assert(assert(EncodeLua(assert(DecodeJson(" [\"a\x00a\"] ")))) == assert(EncodeLua({"a\x00a"})))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_two_commas_in_a_row.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_two_commas_in_a_row.json
assert(assert(EncodeLua(assert(DecodeJson(' {"a":"b",,"c":"d"} ')))) == assert(EncodeLua({a="b", c="d"})))
assert(DecodeJson(' {"a":"b",,"c":"d"} ')) assert(DecodeJson(' {"a":"b",,"c":"d"} '))
assert(EncodeLua(DecodeJson(' {"a":"b",,"c":"d"} ')) == '{a="b", c="d"}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_trailing_comma.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_trailing_comma.json
assert(DecodeJson(' {"id":0,} ')) assert(DecodeJson(' {"id":0,} '))
assert(EncodeLua(DecodeJson(' {"id":0,} ')) == '{id=0}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_several_trailing_commas.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_several_trailing_commas.json
assert(DecodeJson(' {"id":0,,,,,} ')) assert(DecodeJson(' {"id":0,,,,,} '))
assert(EncodeLua(DecodeJson(' {"id":0,,,,,} ')) == '{id=0}')
-- from fail1.lua -- from fail1.lua
--------------------------------------------------------------------------------
-- [jart] v8 permits the \xb9 but doesn't permit the trailing comma
-- therefore this succeeds beacuse we don't care about comma
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json
-- (converted to binary for safety)
assert(DecodeJson(" {\"\xb9\":\"0\",} ")) assert(DecodeJson(" {\"\xb9\":\"0\",} "))
assert(EncodeLua(DecodeJson(" {\"\xb9\":\"0\",} ")) == '{["\\xb9"]="0"}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_missing_semicolon.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_missing_semicolon.json
assert(DecodeJson(' {"a" "b"} ')) assert(DecodeJson(' {"a" "b"} '))
assert(EncodeLua(DecodeJson(' {"a" "b"} ')) == '{a="b"}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_double_colon.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_object_double_colon.json
assert(DecodeJson(' {"x"::"b"} ')) assert(DecodeJson(' {"x"::"b"} '))
assert(EncodeLua(DecodeJson(' {"x"::"b"} ')) == '{x="b"}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_with_leading_zero.json
assert(DecodeJson(' [012] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_real_without_fractional_part.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_real_without_fractional_part.json
assert(DecodeJson(' [1.] ')) assert(DecodeJson(' [1.] '))
assert(EncodeLua(DecodeJson(' [1.] ')) == EncodeLua({1.0}))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_neg_int_starting_with_zero.json
assert(DecodeJson(' [-012] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_minus_space_1.json
assert(DecodeJson(' [- 1] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_2.e3.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_2.e3.json
assert(DecodeJson(' [2.e3] ')) assert(DecodeJson(' [2.e3] '))
assert(EncodeLua(DecodeJson(' [2.e3] ')) == '{2000.}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_2.e-3.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_2.e-3.json
assert(DecodeJson(' [2.e-3] ')) assert(DecodeJson(' [2.e-3] '))
assert(EncodeLua(DecodeJson(' [2.e-3] ')) == '{0.002}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_2.e+3.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_2.e+3.json
assert(DecodeJson(' [2.e+3] ')) assert(DecodeJson(' [2.e+3] '))
assert(EncodeLua(DecodeJson(' [2.e+3] ')) == '{2000.}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_1_000.json
assert(DecodeJson(' [1 000.0] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_0.e1.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_0.e1.json
assert(DecodeJson(' [0.e1] ')) assert(DecodeJson(' [0.e1] '))
assert(EncodeLua(DecodeJson(' [0.e1] ')) == '{0.}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_-2..json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_-2..json
assert(DecodeJson(' [-2.] ')) assert(DecodeJson(' [-2.] '))
assert(EncodeLua(DecodeJson(' [-2.] ')) == '{-2.}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_number_-01.json -- lool
assert(DecodeJson(' [-01] ')) assert(not DecodeJson(' [--2.] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_number_and_several_commas.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_number_and_several_commas.json
assert(DecodeJson(' [1,,] ')) assert(DecodeJson(' [1,,] '))
assert(EncodeLua(DecodeJson(' [1,,] ')) == '{1}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_number_and_comma.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_number_and_comma.json
assert(DecodeJson(' [1,] ')) assert(DecodeJson(' [1,] '))
assert(EncodeLua(DecodeJson(' [1,] ')) == '{1}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_missing_value.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_missing_value.json
assert(DecodeJson(' [ , ""] ')) assert(DecodeJson(' [ , ""] '))
assert(EncodeLua(DecodeJson(' [ , ""] ')) == '{""}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_just_minus.json
assert(DecodeJson(' [-] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_just_comma.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_just_comma.json
assert(DecodeJson(' [,] ')) assert(DecodeJson(' [,] '))
assert(EncodeLua(DecodeJson(' [,] ')) == EncodeLua(DecodeJson(' [] ')))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_inner_array_no_comma.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_inner_array_no_comma.json
-- (added spaces between [[ and ]] so lua doesn't get confused) -- (added spaces between [[ and ]] so lua doesn't get confused)
assert(DecodeJson([[ assert(DecodeJson([[
[ 3[ 4] ] ]])) [ 3[ 4] ] ]]))
assert(EncodeLua(DecodeJson([[
[ 3[ 4] ] ]])) == '{3, {4}}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_extra_comma.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_extra_comma.json
assert(DecodeJson(' ["",] ')) assert(DecodeJson(' ["",] '))
assert(EncodeLua(DecodeJson(' ["",] ')) == '{""}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_double_extra_comma.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_double_extra_comma.json
assert(DecodeJson(' ["x",,] ')) assert(DecodeJson(' ["x",,] '))
assert(EncodeLua(DecodeJson(' ["x",,] ')) == '{"x"}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_double_comma.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_double_comma.json
assert(DecodeJson(' [1,,2] ')) assert(DecodeJson(' [1,,2] '))
assert(EncodeLua(DecodeJson(' [1,,2] ')) == '{1, 2}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_comma_and_number.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_comma_and_number.json
assert(DecodeJson(' [,1] ')) assert(DecodeJson(' [,1] '))
assert(EncodeLua(DecodeJson(' [,1] ')) == '{1}')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_1_true_without_comma.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/n_array_1_true_without_comma.json
assert(DecodeJson(' [1 true] ')) assert(DecodeJson(' [1 true] '))
assert(EncodeLua(DecodeJson(' [1 true] ')) == '{1, true}')

View file

@ -1,4 +1,3 @@
-- --
-- Nicolas Seriot's JSONTestSuite -- Nicolas Seriot's JSONTestSuite
-- https://github.com/nst/JSONTestSuite -- https://github.com/nst/JSONTestSuite
@ -27,18 +26,17 @@
-- SOFTWARE. -- SOFTWARE.
-- --
-- these test cases are prefixed with i_ -- these test cases are prefixed with i_
-- ljson is free to accept or reject, -- ljson is free to accept or reject,
-- but we run them anyway to check for segfaults -- but we run them anyway to check for segfaults
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_structure_UTF-8_BOM_empty_object.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_structure_UTF-8_BOM_empty_object.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \xef\xbb\xbf{} ')) assert(not DecodeJson(' \xef\xbb\xbf{} '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_structure_500_nested_arrays.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_structure_500_nested_arrays.json
-- (added spaces between [[ and ]] so lua doesn't get confused) -- (added spaces between [[ and ]] so lua doesn't get confused)
assert(nil ~= pcall(DecodeJson, [[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ assert(not DecodeJson([[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [
[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [
[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [
[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [
@ -66,124 +64,154 @@ assert(nil ~= pcall(DecodeJson, [[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [
] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ]])) ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ]]))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_utf16LE_no_BOM.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_utf16LE_no_BOM.json
-- (converted to binary for safety) assert(not DecodeJson(" [\x00\"\x00\xe9\x00\"\x00]\x00 "))
assert(nil ~= pcall(DecodeJson, ' \x5b\x00\x22\x00\xe9\x00\x22\x00\x5d\x00 '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_utf16BE_no_BOM.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_utf16BE_no_BOM.json
-- (converted to binary for safety) assert(not DecodeJson(" \x00[\x00\"\x00\xe9\x00\"\x00] "))
assert(nil ~= pcall(DecodeJson, ' \x00\x5b\x00\x22\x00\xe9\x00\x22\x00\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_truncated-utf-8.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_truncated-utf-8.json
-- (converted to binary for safety) assert(DecodeJson(" [\"\xe0\xff\"] "))
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\xe0\xff\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_overlong_sequence_6_bytes_null.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_overlong_sequence_6_bytes_null.json
-- (converted to binary for safety) assert(DecodeJson(" [\"\xfc\x80\x80\x80\x80\x80\"] "))
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\xfc\x80\x80\x80\x80\x80\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_overlong_sequence_6_bytes.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_overlong_sequence_6_bytes.json
-- (converted to binary for safety) assert(DecodeJson(" [\"\xfc\x83\xbf\xbf\xbf\xbf\"] "))
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\xfc\x83\xbf\xbf\xbf\xbf\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_overlong_sequence_2_bytes.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_overlong_sequence_2_bytes.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\xc0\xaf\x22\x5d ')) assert(DecodeJson(' \x5b\x22\xc0\xaf\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_not_in_unicode_range.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_not_in_unicode_range.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\xf4\xbf\xbf\xbf\x22\x5d ')) assert(DecodeJson(" [\"\xf4\xbf\xbf\xbf\"] "))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_lone_utf8_continuation_byte.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_lone_utf8_continuation_byte.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\x81\x22\x5d ')) assert(DecodeJson(' \x5b\x22\x81\x22\x5d '))
-- [jart] our behavior here is consistent with v8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_lone_second_surrogate.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_lone_second_surrogate.json
-- (converted to binary for safety) assert(DecodeJson(" [\"\\uDFAA\"] "))
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\x5c\x75\x44\x46\x41\x41\x22\x5d ')) assert(EncodeJson(DecodeJson(" [\"\\uDFAA\"] ")) == "[\"\\\\uDFAA\"]")
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_iso_latin_1.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_iso_latin_1.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\xe9\x22\x5d ')) assert(DecodeJson(' \x5b\x22\xe9\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_inverted_surrogates_U+1D11E.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_inverted_surrogates_U+1D11E.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\x5c\x75\x44\x64\x31\x65\x5c\x75\x44\x38\x33\x34\x22\x5d ')) assert(DecodeJson(' \x5b\x22\x5c\x75\x44\x64\x31\x65\x5c\x75\x44\x38\x33\x34\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_invalid_utf-8.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_invalid_utf-8.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\xff\x22\x5d ')) assert(DecodeJson(' \x5b\x22\xff\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_invalid_surrogate.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_invalid_surrogate.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\x5c\x75\x64\x38\x30\x30\x61\x62\x63\x22\x5d ')) assert(DecodeJson(' \x5b\x22\x5c\x75\x64\x38\x30\x30\x61\x62\x63\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_invalid_lonely_surrogate.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_invalid_lonely_surrogate.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\x5c\x75\x64\x38\x30\x30\x22\x5d ')) assert(DecodeJson(' \x5b\x22\x5c\x75\x64\x38\x30\x30\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_incomplete_surrogates_escape_valid.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_incomplete_surrogates_escape_valid.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\x5c\x75\x44\x38\x30\x30\x5c\x75\x44\x38\x30\x30\x5c\x6e\x22\x5d ')) assert(DecodeJson(' \x5b\x22\x5c\x75\x44\x38\x30\x30\x5c\x75\x44\x38\x30\x30\x5c\x6e\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_incomplete_surrogate_pair.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_incomplete_surrogate_pair.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\x5c\x75\x44\x64\x31\x65\x61\x22\x5d ')) assert(DecodeJson(' \x5b\x22\x5c\x75\x44\x64\x31\x65\x61\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\x5c\x75\x44\x38\x30\x30\x5c\x6e\x22\x5d ')) assert(DecodeJson(' \x5b\x22\x5c\x75\x44\x38\x30\x30\x5c\x6e\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_UTF8_surrogate_U+D800.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_UTF8_surrogate_U+D800.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\xed\xa0\x80\x22\x5d ')) assert(DecodeJson(' \x5b\x22\xed\xa0\x80\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_UTF-8_invalid_sequence.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_UTF-8_invalid_sequence.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\xe6\x97\xa5\xd1\x88\xfa\x22\x5d ')) assert(DecodeJson(' \x5b\x22\xe6\x97\xa5\xd1\x88\xfa\x22\x5d '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_UTF-16LE_with_BOM.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_UTF-16LE_with_BOM.json
-- (converted to binary for safety) assert(not DecodeJson(" \xff\xfe[\x00\"\x00\xe9\x00\"\x00]\x00 "))
assert(nil ~= pcall(DecodeJson, ' \xff\xfe\x5b\x00\x22\x00\xe9\x00\x22\x00\x5d\x00 '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\x5c\x75\x44\x38\x38\x38\x5c\x75\x31\x32\x33\x34\x22\x5d ')) assert(DecodeJson(' \x5b\x22\x5c\x75\x44\x38\x38\x38\x5c\x75\x31\x32\x33\x34\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_1st_surrogate_but_2nd_missing.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_string_1st_surrogate_but_2nd_missing.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x5b\x22\x5c\x75\x44\x41\x44\x41\x22\x5d ')) assert(DecodeJson(' \x5b\x22\x5c\x75\x44\x41\x44\x41\x22\x5d '))
-- [jart] ljson currently doesn't validate utf-8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_object_key_lone_2nd_surrogate.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_object_key_lone_2nd_surrogate.json
-- (converted to binary for safety) -- (converted to binary for safety)
assert(nil ~= pcall(DecodeJson, ' \x7b\x22\x5c\x75\x44\x46\x41\x41\x22\x3a\x30\x7d ')) assert(DecodeJson(' \x7b\x22\x5c\x75\x44\x46\x41\x41\x22\x3a\x30\x7d '))
-- [jart] ljson is precicely the same as v8 with integers larger than int64_t
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_very_big_negative_int.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_very_big_negative_int.json
assert(nil ~= pcall(DecodeJson, ' [-237462374673276894279832749832423479823246327846] ')) assert(DecodeJson(' [-237462374673276894279832749832423479823246327846] '))
assert(EncodeJson(DecodeJson(' [-237462374673276894279832749832423479823246327846] ')) == '[-2.374623746732769e+47]')
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_too_big_pos_int.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_too_big_pos_int.json
assert(nil ~= pcall(DecodeJson, ' [100000000000000000000] ')) assert(DecodeJson(' [100000000000000000000] '))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_too_big_neg_int.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_too_big_neg_int.json
assert(nil ~= pcall(DecodeJson, ' [-123123123123123123123123123123] ')) assert(DecodeJson(' [-123123123123123123123123123123] '))
-- [jart] once again consistent with v8
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_real_underflow.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_real_underflow.json
assert(nil ~= pcall(DecodeJson, ' [123e-10000000] ')) assert(DecodeJson(' [123e-10000000] '))
assert(EncodeJson(DecodeJson(' [123e-10000000] ')) == '[0]')
assert(EncodeLua(DecodeJson(' [123e-10000000] ')) == '{0.}')
-- [jart] consistent with v8 we encode Infinity as null (wut?)
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_real_pos_overflow.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_real_pos_overflow.json
assert(nil ~= pcall(DecodeJson, ' [123123e100000] ')) assert(DecodeJson(' [123123e100000] '))
assert(EncodeJson(DecodeJson(' [123123e100000] ')) == '[null]')
-- [jart] consistent with v8 we encode -Infinity as null (wut?)
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_real_neg_overflow.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_real_neg_overflow.json
assert(nil ~= pcall(DecodeJson, ' [-123123e100000] ')) assert(DecodeJson(' [-123123e100000] '))
assert(EncodeJson(DecodeJson(' [-123123e100000] ')) == '[null]')
-- [jart] consistent with v8 we encode Infinity as null (wut?)
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_pos_double_huge_exp.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_pos_double_huge_exp.json
assert(nil ~= pcall(DecodeJson, ' [1.5e+9999] ')) assert(DecodeJson(' [1.5e+9999] '))
assert(EncodeJson(DecodeJson(' [1.5e+9999] ')) == '[null]')
-- [jart] consistent with v8 we encode -Infinity as null (wut?)
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_neg_int_huge_exp.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_neg_int_huge_exp.json
assert(nil ~= pcall(DecodeJson, ' [-1e+9999] ')) assert(DecodeJson(' [-1e+9999] '))
assert(EncodeJson(DecodeJson(' [-1e+9999] ')) == '[null]')
-- [jart] consistent with v8 we encode Infinity as null (wut?)
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_huge_exp.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_huge_exp.json
assert(nil ~= pcall(DecodeJson, ' [0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006] ')) assert(DecodeJson(' [0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006] '))
assert(EncodeJson(DecodeJson(' [0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006] ')) == '[null]')
-- [jart] consistent with v8 we encode underflow as 0
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_double_huge_neg_exp.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/i_number_double_huge_neg_exp.json
assert(nil ~= pcall(DecodeJson, ' [123.456e-789] ')) assert(DecodeJson(' [123.456e-789] '))
assert(EncodeJson(DecodeJson(' [123.456e-789] ')) == '[0]')

View file

@ -1,4 +1,3 @@
-- --
-- Nicolas Seriot's JSONTestSuite -- Nicolas Seriot's JSONTestSuite
-- https://github.com/nst/JSONTestSuite -- https://github.com/nst/JSONTestSuite
@ -27,10 +26,21 @@
-- SOFTWARE. -- SOFTWARE.
-- --
-- these test cases are prefixed with y_ -- these test cases are prefixed with y_
-- ljson should accept all of them as valid -- ljson should accept all of them as valid
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_lonely_null.json
val, err = DecodeJson([[ null ]])
assert(not val)
assert(val == nil)
assert(err == nil)
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_lonely_false.json
val, err = DecodeJson([[ false ]])
assert(not val)
assert(val == false)
assert(err == nil)
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_whitespace_array.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_whitespace_array.json
assert(DecodeJson([[ [] ]])) assert(DecodeJson([[ [] ]]))
@ -49,27 +59,29 @@ assert(DecodeJson([[ true ]]))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_lonely_string.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_lonely_string.json
assert(DecodeJson([[ "asd" ]])) assert(DecodeJson([[ "asd" ]]))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_lonely_null.json
assert(not DecodeJson([[ null ]]))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_lonely_negative_real.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_lonely_negative_real.json
assert(DecodeJson([[ -0.1 ]])) assert(DecodeJson([[ -0.1 ]]))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_lonely_int.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_lonely_int.json
assert(DecodeJson([[ 42 ]])) assert(DecodeJson([[ 42 ]]))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_structure_lonely_false.json -- Raw ASCII DEL allowed in string literals
assert(not DecodeJson([[ false ]]))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_with_del_character.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_with_del_character.json
assert(DecodeJson([[ ["aa"] ]])) assert(DecodeJson(" [\"a\x7fa\"] "))
assert(EncodeJson(DecodeJson(" [\"a\x7fa\"] ")) == '["a\\u007fa"]')
-- EURO SIGN (20AC) and MUSICAL SYMBOL G CLEF (1D11E) in string literal
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_utf8.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_utf8.json
assert(DecodeJson([[ ["€𝄞"] ]])) assert(DecodeJson([[ ["€𝄞"] ]]))
assert(EncodeJson(DecodeJson([[ ["€𝄞"] ]])) == "[\"\\u20ac\\ud834\\udd1e\"]")
assert(EncodeJson(DecodeJson([[ ["€𝄞"] ]])) == EncodeJson(DecodeJson(" [\"\xe2\x82\xac\xf0\x9d\x84\x9e\"] ")))
-- unicode escape for double quote
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_unicode_escaped_double_quote.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_unicode_escaped_double_quote.json
assert(DecodeJson([[ ["\u0022"] ]])) assert(DecodeJson([[ ["\u0022"] ]]))
assert(DecodeJson([[ ["\u0022"] ]])[1] == '"')
-- replacement character
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_unicode_U+FFFE_nonchar.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_unicode_U+FFFE_nonchar.json
assert(DecodeJson([[ ["\uFFFE"] ]])) assert(DecodeJson([[ ["\uFFFE"] ]]))
@ -106,9 +118,11 @@ assert(DecodeJson([[ ["new\u000Aline"] ]]))
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_uEscape.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_uEscape.json
assert(DecodeJson([[ ["\u0061\u30af\u30EA\u30b9"] ]])) assert(DecodeJson([[ ["\u0061\u30af\u30EA\u30b9"] ]]))
-- paragraph separator trojan source
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_u+2029_par_sep.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_u+2029_par_sep.json
assert(DecodeJson([[ [""] ]])) assert(DecodeJson([[ [""] ]]))
-- line separator trojan source
-- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_u+2028_line_sep.json -- https://github.com/nst/JSONTestSuite/tree/d64aefb55228d9584d3e5b2433f720ea8fd00c82/test_parsing/y_string_u+2028_line_sep.json
assert(DecodeJson([[ [""] ]])) assert(DecodeJson([[ [""] ]]))
@ -322,4 +336,3 @@ assert(DecodeJson([[ [""] ]]))
-- (added spaces between [[ and ]] so lua doesn't get confused) -- (added spaces between [[ and ]] so lua doesn't get confused)
assert(DecodeJson([[ assert(DecodeJson([[
[ [ ] ] ]])) [ [ ] ] ]]))

View file

@ -9,30 +9,35 @@ assert(DecodeJson([[
[ "extra comma",] [ "extra comma",]
]])) ]]))
-- [jart] we deviate from json.org because we don't care about commas
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail5.json -- JSON parsing sample test case: fail5.json
assert(DecodeJson([[ assert(DecodeJson([[
[ "double extra comma",,] [ "double extra comma",,]
]])) ]]))
-- [jart] we deviate from json.org because we don't care about commas
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail6.json -- JSON parsing sample test case: fail6.json
assert(DecodeJson([[ assert(DecodeJson([[
[ , "<-- missing value"] [ , "<-- missing value"]
]])) ]]))
-- [jart] we deviate from json.org because we don't care about commas
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail9.json -- JSON parsing sample test case: fail9.json
assert(DecodeJson([[ assert(DecodeJson([[
{"Extra comma": true,} {"Extra comma": true,}
]])) ]]))
-- [jart] we deviate from json.org because we don't care about colons
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail19.json -- JSON parsing sample test case: fail19.json
assert(DecodeJson([[ assert(DecodeJson([[
{"Missing colon" null} {"Missing colon" null}
]])) ]]))
-- [jart] we deviate from json.org because we don't care about colons
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail20.json -- JSON parsing sample test case: fail20.json
assert(DecodeJson([[ assert(DecodeJson([[
@ -41,19 +46,19 @@ assert(DecodeJson([[
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail25.json -- JSON parsing sample test case: fail25.json
assert(DecodeJson([[ assert(not DecodeJson([[
[ " tab character in string "] [ " tab character in string "]
]])) ]]))
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail27.json -- JSON parsing sample test case: fail27.json
assert(DecodeJson([[ assert(not DecodeJson([[
[ "line [ "line
break"] break"]
]])) ]]))
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail15.json -- JSON parsing sample test case: fail15.json
assert(DecodeJson([[ assert(not DecodeJson([[
[ "Illegal backslash escape: \x15"] [ "Illegal backslash escape: \x15"]
]])) ]]))

View file

@ -1,6 +1,6 @@
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: pass1.json -- JSON parsing sample test case: pass1.json
assert(pcall(DecodeJson, [[ assert(DecodeJson([[
[ [
"JSON Test Pattern pass1", "JSON Test Pattern pass1",
{"object with 1 member":[ "array with 1 element"] }, {"object with 1 member":[ "array with 1 element"] },
@ -63,14 +63,13 @@ assert(pcall(DecodeJson, [[
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: pass2.json -- JSON parsing sample test case: pass2.json
assert(pcall(DecodeJson, [[ assert(DecodeJson([[
[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ "Not too deep"] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ "Not too deep"] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ]
]])) ]]))
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: pass3.json -- JSON parsing sample test case: pass3.json
assert(pcall(DecodeJson, [[ assert(DecodeJson([[
{ {
"JSON Test Pattern pass3": { "JSON Test Pattern pass3": {
"The outermost value": "must be an object or array.", "The outermost value": "must be an object or array.",
@ -80,18 +79,20 @@ assert(pcall(DecodeJson, [[
]])) ]]))
-- json.org says these should fail, but many parsers, -- json.org says these should fail, but many parsers,
-- including python's json.load allow the following -- including python's json.load allow the following
-- [jart] our behavior is consistent with v8
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail1.json (actually passes) -- JSON parsing sample test case: fail1.json (actually passes)
assert(pcall(DecodeJson, [[ assert(DecodeJson([[
"A JSON payload should be an object or array, not a string." "A JSON payload should be an object or array, not a string."
]])) ]]))
-- [jart] this deviates from json.org
-- we permit depth up to 128
-- https://www.json.org/JSON_checker/test.zip -- https://www.json.org/JSON_checker/test.zip
-- JSON parsing sample test case: fail18.json (actually passes) -- JSON parsing sample test case: fail18.json (actually passes)
assert(pcall(DecodeJson, [[ assert(DecodeJson([[
[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ "Too deep"] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ "Too deep"] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ]
]])) ]]))

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/bits.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "third_party/double-conversion/double-conversion.h" #include "third_party/double-conversion/double-conversion.h"
#include "third_party/double-conversion/double-to-string.h" #include "third_party/double-conversion/double-to-string.h"
@ -32,6 +33,21 @@ char* DoubleToEcmascript(char buf[128], double x) {
return b.Finalize(); return b.Finalize();
} }
char* DoubleToJson(char buf[128], double x) {
StringBuilder b(buf, 128);
static const DoubleToStringConverter kDoubleToJson(
DoubleToStringConverter::UNIQUE_ZERO |
DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN,
"null", "null", 'e', -6, 21, 6, 0);
kDoubleToJson.ToShortest(x, &b);
b.Finalize();
if (READ32LE(buf) != READ32LE("-nul")) {
return buf;
} else {
return strcpy(buf, "null");
}
}
char* DoubleToLua(char buf[128], double x) { char* DoubleToLua(char buf[128], double x) {
static const DoubleToStringConverter kDoubleToLua( static const DoubleToStringConverter kDoubleToLua(
DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT | DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT |

View file

@ -4,6 +4,7 @@
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
char *DoubleToLua(char[128], double); char *DoubleToLua(char[128], double);
char *DoubleToJson(char[128], double);
char *DoubleToEcmascript(char[128], double); char *DoubleToEcmascript(char[128], double);
double StringToDouble(const char *, size_t, int *); double StringToDouble(const char *, size_t, int *);

View file

@ -74,7 +74,7 @@ static int LuaEncodeJsonDataImpl(lua_State *L, char **buf, int level,
buf, ibuf, FormatInt64(ibuf, luaL_checkinteger(L, idx)) - ibuf)); buf, ibuf, FormatInt64(ibuf, luaL_checkinteger(L, idx)) - ibuf));
} else { } else {
RETURN_ON_ERROR( RETURN_ON_ERROR(
appends(buf, DoubleToEcmascript(ibuf, lua_tonumber(L, idx)))); appends(buf, DoubleToJson(ibuf, lua_tonumber(L, idx))));
} }
return 0; return 0;

View file

@ -679,21 +679,61 @@ FUNCTIONS
├─→ double ├─→ double
├─→ array ├─→ array
├─→ object ├─→ object
├─→ false
├─→ true ├─→ true
├─→ nil
└─→ nil, error:str └─→ nil, error:str
Turns JSON string into a Lua data structure. Turns JSON string into a Lua data structure.
This is a very permissive parser. That means it should always This is a generally permissive parser, in the sense that like
parse correctly formatted JSON correctly. However it will not v8, it permits scalars as top-level values. Therefore we must
complain if the `input` string is weirdly formatted. There is note that this API can be thought of as special, in the sense
currently no validation performed, other than what we need to
ensure security. For example `{3=4}` will decode as `{[3]=4}`
even though that structure won't round-trip with `EncodeJson`
since redbean won't generate invalid JSON (see Postel's Law).
This parser permits top-level values regardless of type, with val = assert(DecodeJson(str))
the exception of `false`, `null`, and absent.
will usually do the right thing, except in cases where false
or null are the top-level value. In those cases, it's needed
to check the second value too in order to discern from error
val, err = DecodeJson(str)
if not val then
if err then
print('bad json', err)
elseif val == nil then
print('val is null')
elseif val == false then
print('val is false')
end
end
This parser supports 64-bit signed integers. If an overflow
happens, then the integer is silently coerced to double, as
consistent with v8. If a double overflows into Infinity, we
coerce it to `null` since that's what v8 does, and the same
goes for underflows which, like v8, are coerced to 0.0.
This parser does not validate UTF-8 which is copied how the
JSON specifies. It may therefore contain underlong overlong
characters, trojan source and even numbers banned the IETF.
You can use VisualizeControlCodes() and Underlong(), to see
if a string round-trips, to detect these weirdo codepoints.
This parser does some validation of UTF-16. Consistent with
v8, bad surrogate characters will be silently preserved, as
their original escape sequence text. Thereby ensuring utf-8
output is valid. Please note that invalid utf-8 could still
happen if it's encoded as utf-8.
This parser is lenient about commas and colons. For example
it's permissible to say `DecodeJson('[1 2 3 4]')`. Trailing
commas are allowed. Even prefix commas are allowed. However
it's not recommended that you rely on this behavior, and it
won't round-trip with EncodeJson() currently.
When objects are parsed, your Lua object can't preserve the
the original ordering of fields. As such, they'll be sorted
by EncodeJson() and may not round-trip with original intent
EncodeJson(value[,options:table]) EncodeJson(value[,options:table])
├─→ json:str ├─→ json:str
@ -726,6 +766,8 @@ FUNCTIONS
When arrays and objects are serialized, entries will be sorted When arrays and objects are serialized, entries will be sorted
in a deterministic order. in a deterministic order.
This parser does not support UTF-8
EncodeLua(value[,options:table]) EncodeLua(value[,options:table])
├─→ luacode:str ├─→ luacode:str
├─→ true [if useoutput] ├─→ true [if useoutput]
@ -1385,10 +1427,10 @@ FUNCTIONS
access log and message logging. access log and message logging.
VisualizeControlCodes(str) → str VisualizeControlCodes(str) → str
Replaces C0 control codes with their UNICODE pictures Replaces C0 control codes and trojan source characters with
representation. This function also canonicalizes overlong descriptive UNICODE pictorial representation. This function
encodings. C1 control codes are replaced with a JavaScript-like also canonicalizes overlong encodings. C1 control codes are
escape sequence. replaced with a JavaScript-like escape sequence.
Underlong(str) → str Underlong(str) → str
Canonicalizes overlong encodings. Canonicalizes overlong encodings.

View file

@ -19,7 +19,9 @@
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/bits/likely.h" #include "libc/bits/likely.h"
#include "libc/intrin/kprintf.h" #include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h" #include "libc/str/tpenc.h"
#include "libc/str/utf16.h" #include "libc/str/utf16.h"
#include "third_party/double-conversion/wrapper.h" #include "third_party/double-conversion/wrapper.h"
@ -42,6 +44,7 @@ static struct DecodeJson Parse(struct lua_State *L, const char *p,
char w[4]; char w[4];
const char *a; const char *a;
luaL_Buffer b; luaL_Buffer b;
const char *reason;
struct DecodeJson r; struct DecodeJson r;
int A, B, C, D, c, d, i, u; int A, B, C, D, c, d, i, u;
if (UNLIKELY(!--depth)) { if (UNLIKELY(!--depth)) {
@ -74,9 +77,6 @@ static struct DecodeJson Parse(struct lua_State *L, const char *p,
case 'n': // null case 'n': // null
if (UNLIKELY(context == OBJECT_KEY)) goto BadObjectKey; if (UNLIKELY(context == OBJECT_KEY)) goto BadObjectKey;
if (UNLIKELY(context == TOP_LEVEL)) {
return (struct DecodeJson){-1, "toplevel json can't be null"};
}
if (p + 3 <= e && READ32LE(p - 1) == READ32LE("null")) { if (p + 3 <= e && READ32LE(p - 1) == READ32LE("null")) {
lua_pushnil(L); lua_pushnil(L);
return (struct DecodeJson){1, p + 3}; return (struct DecodeJson){1, p + 3};
@ -86,9 +86,6 @@ static struct DecodeJson Parse(struct lua_State *L, const char *p,
case 'f': // false case 'f': // false
if (UNLIKELY(context == OBJECT_KEY)) goto BadObjectKey; if (UNLIKELY(context == OBJECT_KEY)) goto BadObjectKey;
if (UNLIKELY(context == TOP_LEVEL)) {
return (struct DecodeJson){-1, "toplevel json can't be false"};
}
if (p + 4 <= e && READ32LE(p) == READ32LE("alse")) { if (p + 4 <= e && READ32LE(p) == READ32LE("alse")) {
lua_pushboolean(L, false); lua_pushboolean(L, false);
return (struct DecodeJson){1, p + 4}; return (struct DecodeJson){1, p + 4};
@ -105,15 +102,26 @@ static struct DecodeJson Parse(struct lua_State *L, const char *p,
goto IllegalCharacter; goto IllegalCharacter;
} }
BadObjectKey:
return (struct DecodeJson){-1, "object key must be string"};
case '-': // negative case '-': // negative
if (UNLIKELY(context == OBJECT_KEY)) goto BadObjectKey; if (UNLIKELY(context == OBJECT_KEY)) goto BadObjectKey;
d = -1; if (p < e && isdigit(*p)) {
break; d = -1;
break;
} else {
return (struct DecodeJson){-1, "bad negative"};
}
case '0': // zero or number case '0': // zero or number
if (UNLIKELY(context == OBJECT_KEY)) goto BadObjectKey; if (UNLIKELY(context == OBJECT_KEY)) goto BadObjectKey;
if (p < e && (*p == '.' || *p == 'e' || *p == 'E')) { if (p < e) {
goto UseDubble; if ((*p == '.' || *p == 'e' || *p == 'E')) {
goto UseDubble;
} else if (isdigit(*p)) {
return (struct DecodeJson){-1, "unexpected octal"};
}
} }
lua_pushinteger(L, 0); lua_pushinteger(L, 0);
return (struct DecodeJson){1, p}; return (struct DecodeJson){1, p};
@ -138,6 +146,7 @@ static struct DecodeJson Parse(struct lua_State *L, const char *p,
UseDubble: // number UseDubble: // number
lua_pushnumber(L, StringToDouble(a, e - a, &c)); lua_pushnumber(L, StringToDouble(a, e - a, &c));
DCHECK(c > 0, "paranoid avoiding infinite loop");
return (struct DecodeJson){1, a + c}; return (struct DecodeJson){1, a + c};
case '[': // Array case '[': // Array
@ -206,134 +215,146 @@ static struct DecodeJson Parse(struct lua_State *L, const char *p,
case '"': // string case '"': // string
luaL_buffinit(L, &b); luaL_buffinit(L, &b);
while (p < e) { for (;;) {
if (UNLIKELY(p >= e)) {
UnexpectedEofString:
reason = "unexpected eof in string";
goto StringFailureWithReason;
}
c = *p++ & 255;
if (c == '"') {
luaL_pushresult(&b);
return (struct DecodeJson){1, p};
} else if (c == '\\') {
goto HandleEscape;
} else if (UNLIKELY(c <= 0x1F)) {
reason = "non-del c0 in string";
goto StringFailureWithReason;
} else {
luaL_addchar(&b, c);
}
continue;
HandleEscape:
if (UNLIKELY(p >= e)) {
goto UnexpectedEofString;
}
switch ((c = *p++ & 255)) { switch ((c = *p++ & 255)) {
default: case '"':
AddByte: case '/':
case '\\':
luaL_addchar(&b, c); luaL_addchar(&b, c);
break; break;
case '\\': case 'b':
if (p < e) { luaL_addchar(&b, '\b');
switch ((c = *p++ & 255)) { break;
default: case 'f':
goto InvalidEscapeCharacter; luaL_addchar(&b, '\f');
case '"': break;
case '/': case 'n':
case '\\': luaL_addchar(&b, '\n');
goto AddByte; break;
case 'b': case 'r':
c = '\b'; luaL_addchar(&b, '\r');
goto AddByte; break;
case 'f': case 't':
c = '\f'; luaL_addchar(&b, '\t');
goto AddByte; break;
case 'n': case 'x':
c = '\n'; if (p + 2 <= e && //
goto AddByte; (A = kHexToInt[p[0] & 255]) != -1 && // HEX
case 'r': (B = kHexToInt[p[1] & 255]) != -1) { //
c = '\r'; c = A << 4 | B;
goto AddByte; if (!(0x20 <= c && c <= 0x7E)) {
case 't': reason = "hex escape not printable";
c = '\t'; goto StringFailureWithReason;
goto AddByte;
case 'x':
if (p + 2 <= e && //
(A = kHexToInt[p[0] & 255]) != -1 && // HEX
(B = kHexToInt[p[1] & 255]) != -1) { //
c = A << 4 | B;
p += 2;
goto AddByte;
} else {
goto InvalidEscapeCharacter;
}
case 'u':
if (p + 4 <= e && //
(A = kHexToInt[p[0] & 255]) != -1 && //
(B = kHexToInt[p[1] & 255]) != -1 && // UCS-2
(C = kHexToInt[p[2] & 255]) != -1 && //
(D = kHexToInt[p[3] & 255]) != -1) { //
c = A << 12 | B << 8 | C << 4 | D;
if (!IsSurrogate(c)) {
p += 4;
} else if (IsHighSurrogate(c)) {
if (p + 4 + 6 <= e && //
p[4] == '\\' && //
p[5] == 'u' && //
(A = kHexToInt[p[6] & 255]) != -1 && // UTF-16
(B = kHexToInt[p[7] & 255]) != -1 && //
(C = kHexToInt[p[8] & 255]) != -1 && //
(D = kHexToInt[p[9] & 255]) != -1) { //
u = A << 12 | B << 8 | C << 4 | D;
if (IsLowSurrogate(u)) {
p += 4 + 6;
c = MergeUtf16(c, u);
} else {
goto BadUnicode;
}
} else {
goto BadUnicode;
}
} else {
goto BadUnicode;
}
// UTF-8
if (c < 0x7f) {
w[0] = c;
i = 1;
} else if (c <= 0x7ff) {
w[0] = 0300 | (c >> 6);
w[1] = 0200 | (c & 077);
i = 2;
} else if (c <= 0xffff) {
if (UNLIKELY(IsSurrogate(c))) {
ReplacementCharacter:
c = 0xfffd;
}
w[0] = 0340 | (c >> 12);
w[1] = 0200 | ((c >> 6) & 077);
w[2] = 0200 | (c & 077);
i = 3;
} else if (~(c >> 18) & 007) {
w[0] = 0360 | (c >> 18);
w[1] = 0200 | ((c >> 12) & 077);
w[2] = 0200 | ((c >> 6) & 077);
w[3] = 0200 | (c & 077);
i = 4;
} else {
goto ReplacementCharacter;
}
luaL_addlstring(&b, w, i);
} else {
goto InvalidEscapeCharacter;
BadUnicode:
// Echo invalid \uXXXX sequences
// Rather than corrupting UTF-8!
luaL_addstring(&b, "\\u");
}
break;
} }
p += 2;
luaL_addchar(&b, c);
break;
} else { } else {
goto InvalidEscapeCharacter; reason = "invalid hex escape";
goto StringFailureWithReason;
}
case 'u':
if (p + 4 <= e && //
(A = kHexToInt[p[0] & 255]) != -1 && //
(B = kHexToInt[p[1] & 255]) != -1 && // UCS-2
(C = kHexToInt[p[2] & 255]) != -1 && //
(D = kHexToInt[p[3] & 255]) != -1) { //
c = A << 12 | B << 8 | C << 4 | D;
if (!IsSurrogate(c)) {
p += 4;
} else if (IsHighSurrogate(c)) {
if (p + 4 + 6 <= e && //
p[4] == '\\' && //
p[5] == 'u' && //
(A = kHexToInt[p[6] & 255]) != -1 && // UTF-16
(B = kHexToInt[p[7] & 255]) != -1 && //
(C = kHexToInt[p[8] & 255]) != -1 && //
(D = kHexToInt[p[9] & 255]) != -1) { //
u = A << 12 | B << 8 | C << 4 | D;
if (IsLowSurrogate(u)) {
p += 4 + 6;
c = MergeUtf16(c, u);
} else {
goto BadUnicode;
}
} else {
goto BadUnicode;
}
} else {
goto BadUnicode;
}
// UTF-8
if (c < 0x7f) {
w[0] = c;
i = 1;
} else if (c <= 0x7ff) {
w[0] = 0300 | (c >> 6);
w[1] = 0200 | (c & 077);
i = 2;
} else if (c <= 0xffff) {
if (UNLIKELY(IsSurrogate(c))) {
ReplacementCharacter:
c = 0xfffd;
}
w[0] = 0340 | (c >> 12);
w[1] = 0200 | ((c >> 6) & 077);
w[2] = 0200 | (c & 077);
i = 3;
} else if (~(c >> 18) & 007) {
w[0] = 0360 | (c >> 18);
w[1] = 0200 | ((c >> 12) & 077);
w[2] = 0200 | ((c >> 6) & 077);
w[3] = 0200 | (c & 077);
i = 4;
} else {
goto ReplacementCharacter;
}
luaL_addlstring(&b, w, i);
} else {
reason = "invalid unicode escape";
goto StringFailureWithReason;
BadUnicode:
// Echo invalid \uXXXX sequences
// Rather than corrupting UTF-8!
luaL_addstring(&b, "\\u");
} }
break; break;
case '"': default:
luaL_pushresult(&b); reason = "invalid escape character";
return (struct DecodeJson){1, p}; goto StringFailureWithReason;
} }
} }
break;
StringFailureWithReason:
luaL_pushresultsize(&b, 0); luaL_pushresultsize(&b, 0);
lua_pop(L, 1); lua_pop(L, 1);
return (struct DecodeJson){-1, "unexpected eof in string"}; return (struct DecodeJson){-1, reason};
default: default:
IllegalCharacter: IllegalCharacter:
return (struct DecodeJson){-1, "illegal character"}; return (struct DecodeJson){-1, "illegal character"};
BadObjectKey:
return (struct DecodeJson){-1, "object key must be string"};
InvalidEscapeCharacter:
luaL_pushresultsize(&b, 0);
lua_pop(L, 1);
return (struct DecodeJson){-1, "invalid escape character"};
} }
} }
if (UNLIKELY(context == TOP_LEVEL)) { if (UNLIKELY(context == TOP_LEVEL)) {
@ -357,16 +378,14 @@ static struct DecodeJson Parse(struct lua_State *L, const char *p,
* converted to a floating-point number instead. Invalid surrogate * converted to a floating-point number instead. Invalid surrogate
* escape sequences in strings won't be decoded. * escape sequences in strings won't be decoded.
* *
* A weird case exists when parsing empty objects. In order to let Lua
* tell them apart from empty arrays, we insert a special key that's
* ignored by our JSON serializer, called `[__json_object__]=true`.
*
* @param L is Lua interpreter state * @param L is Lua interpreter state
* @param p is input string * @param p is input string
* @param n is byte length of `p` or -1 for automatic strlen() * @param n is byte length of `p` or -1 for automatic strlen()
* @return res.rc is 1 if value pushed, 0 on eof, otherwise -1 * @return r.rc is 1 if value is pushed on lua stack
* @return res.p is is advanced `p` pointer if `rc` isn't -1 * @return r.rc is 0 on eof
* @return res.p is string describing error if `rc` is -1 * @return r.rc is -1 on error
* @return r.p is is advanced `p` pointer if `rc 0`
* @return r.p is string describing error if `rc < 0`
*/ */
struct DecodeJson DecodeJson(struct lua_State *L, const char *p, size_t n) { struct DecodeJson DecodeJson(struct lua_State *L, const char *p, size_t n) {
if (n == -1) n = p ? strlen(p) : 0; if (n == -1) n = p ? strlen(p) : 0;