diff --git a/src/json.hpp b/src/json.hpp index 13a821ec..bba7f85a 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8934,6 +8934,11 @@ basic_json_parser_66: // skip the next 10 characters (xxxx\uyyyy) i += 10; } + else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF) + { + // we found a lone low surrogate + throw std::invalid_argument("missing high surrogate"); + } else { // add unicode character(s) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index f6884cb4..77add1a2 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8083,6 +8083,11 @@ class basic_json // skip the next 10 characters (xxxx\uyyyy) i += 10; } + else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF) + { + // we found a lone low surrogate + throw std::invalid_argument("missing high surrogate"); + } else { // add unicode character(s) diff --git a/test/data/nst_json_testsuite/test_parsing/n_structure_<.>.json b/test/data/nst_json_testsuite/test_parsing/n_structure_3C.3E.json similarity index 100% rename from test/data/nst_json_testsuite/test_parsing/n_structure_<.>.json rename to test/data/nst_json_testsuite/test_parsing/n_structure_3C.3E.json diff --git a/test/data/nst_json_testsuite/test_parsing/n_structure_.json b/test/data/nst_json_testsuite/test_parsing/n_structure_3Cnull3E.json similarity index 100% rename from test/data/nst_json_testsuite/test_parsing/n_structure_.json rename to test/data/nst_json_testsuite/test_parsing/n_structure_3Cnull3E.json diff --git a/test/src/unit-testsuites.cpp b/test/src/unit-testsuites.cpp index 8137158f..6c3f21f3 100644 --- a/test/src/unit-testsuites.cpp +++ b/test/src/unit-testsuites.cpp @@ -703,8 +703,8 @@ TEST_CASE("nst's JSONTestSuite") "test/data/nst_json_testsuite/test_parsing/n_string_unicode_CapitalU.json", "test/data/nst_json_testsuite/test_parsing/n_string_with_trailing_garbage.json", //!"test/data/nst_json_testsuite/test_parsing/n_structure_100000_opening_arrays.json", - "test/data/nst_json_testsuite/test_parsing/n_structure_<.>.json", - "test/data/nst_json_testsuite/test_parsing/n_structure_.json", + "test/data/nst_json_testsuite/test_parsing/n_structure_3C.3E.json", + "test/data/nst_json_testsuite/test_parsing/n_structure_3Cnull3E.json", "test/data/nst_json_testsuite/test_parsing/n_structure_U+2060_word_joined.json", "test/data/nst_json_testsuite/test_parsing/n_structure_UTF8_BOM_no_data.json", "test/data/nst_json_testsuite/test_parsing/n_structure_array_trailing_garbage.json", @@ -761,31 +761,22 @@ TEST_CASE("nst's JSONTestSuite") } } - SECTION("i") + SECTION("i -> y") { for (auto filename : { + // we currently do not limit exponents "test/data/nst_json_testsuite/test_parsing/i_number_neg_int_huge_exp.json", "test/data/nst_json_testsuite/test_parsing/i_number_pos_double_huge_exp.json", - "test/data/nst_json_testsuite/test_parsing/i_object_key_lone_2nd_surrogate.json", - //"test/data/nst_json_testsuite/test_parsing/i_string_1st_surrogate_but_2nd_missing.json", - //"test/data/nst_json_testsuite/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json", - //"test/data/nst_json_testsuite/test_parsing/i_string_UTF-16_invalid_lonely_surrogate.json", - //"test/data/nst_json_testsuite/test_parsing/i_string_UTF-16_invalid_surrogate.json", - //"test/data/nst_json_testsuite/test_parsing/i_string_UTF-8_invalid_sequence.json", - //"test/data/nst_json_testsuite/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json", - "test/data/nst_json_testsuite/test_parsing/i_string_incomplete_surrogate_pair.json", - //"test/data/nst_json_testsuite/test_parsing/i_string_incomplete_surrogates_escape_valid.json", - //"test/data/nst_json_testsuite/test_parsing/i_string_inverted_surrogates_U+1D11E.json", - "test/data/nst_json_testsuite/test_parsing/i_string_lone_second_surrogate.json", - //"test/data/nst_json_testsuite/test_parsing/i_string_not_in_unicode_range.json", - //"test/data/nst_json_testsuite/test_parsing/i_string_truncated-utf-8.json", + // we do not pose a limit on nesting + "test/data/nst_json_testsuite/test_parsing/i_structure_500_nested_arrays.json", + // we silently ignore BOMs + "test/data/nst_json_testsuite/test_parsing/i_structure_UTF-8_BOM_empty_object.json", + // we accept and forward non-characters "test/data/nst_json_testsuite/test_parsing/i_string_unicode_U+10FFFE_nonchar.json", "test/data/nst_json_testsuite/test_parsing/i_string_unicode_U+1FFFE_nonchar.json", "test/data/nst_json_testsuite/test_parsing/i_string_unicode_U+FDD0_nonchar.json", - "test/data/nst_json_testsuite/test_parsing/i_string_unicode_U+FFFE_nonchar.json", - "test/data/nst_json_testsuite/test_parsing/i_structure_500_nested_arrays.json", - "test/data/nst_json_testsuite/test_parsing/i_structure_UTF-8_BOM_empty_object.json" + "test/data/nst_json_testsuite/test_parsing/i_string_unicode_U+FFFE_nonchar.json" } ) { @@ -796,5 +787,31 @@ TEST_CASE("nst's JSONTestSuite") } } + SECTION("i -> n") + { + for (auto filename : + { + "test/data/nst_json_testsuite/test_parsing/i_object_key_lone_2nd_surrogate.json", + "test/data/nst_json_testsuite/test_parsing/i_string_1st_surrogate_but_2nd_missing.json", + "test/data/nst_json_testsuite/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json", + "test/data/nst_json_testsuite/test_parsing/i_string_UTF-16_invalid_lonely_surrogate.json", + "test/data/nst_json_testsuite/test_parsing/i_string_UTF-16_invalid_surrogate.json", + "test/data/nst_json_testsuite/test_parsing/i_string_UTF-8_invalid_sequence.json", + "test/data/nst_json_testsuite/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json", + "test/data/nst_json_testsuite/test_parsing/i_string_incomplete_surrogate_pair.json", + "test/data/nst_json_testsuite/test_parsing/i_string_incomplete_surrogates_escape_valid.json", + "test/data/nst_json_testsuite/test_parsing/i_string_inverted_surrogates_U+1D11E.json", + "test/data/nst_json_testsuite/test_parsing/i_string_lone_second_surrogate.json", + "test/data/nst_json_testsuite/test_parsing/i_string_not_in_unicode_range.json", + "test/data/nst_json_testsuite/test_parsing/i_string_truncated-utf-8.json" + } + ) + { + CAPTURE(filename); + std::ifstream f(filename); + json j; + CHECK_THROWS_AS(j << f, std::invalid_argument); + } + } } }