From b1b789df4203296a848fec6a3513f30efceb1a45 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Tue, 6 Feb 2024 15:30:29 -0500 Subject: [PATCH] Detect end of input inside an unfinished JSON string --- .../9bc1baa450a0977fb3ac06c1ddb3fc2d4c05a5ce | 1 + fuzz/qtest/fuzz.test | 2 +- libqpdf/JSON.cc | 5 +++-- libtests/json.cc | 6 ++++++ 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 fuzz/json_fuzzer_seed_corpus/9bc1baa450a0977fb3ac06c1ddb3fc2d4c05a5ce diff --git a/fuzz/json_fuzzer_seed_corpus/9bc1baa450a0977fb3ac06c1ddb3fc2d4c05a5ce b/fuzz/json_fuzzer_seed_corpus/9bc1baa450a0977fb3ac06c1ddb3fc2d4c05a5ce new file mode 100644 index 00000000..09495bc1 --- /dev/null +++ b/fuzz/json_fuzzer_seed_corpus/9bc1baa450a0977fb3ac06c1ddb3fc2d4c05a5ce @@ -0,0 +1 @@ +{"qpdf":[{},{"obj:1 0 R":{"stream":{"data":" \ No newline at end of file diff --git a/fuzz/qtest/fuzz.test b/fuzz/qtest/fuzz.test index 28676339..7235140d 100644 --- a/fuzz/qtest/fuzz.test +++ b/fuzz/qtest/fuzz.test @@ -16,7 +16,7 @@ my @fuzzers = ( ['dct' => 1], ['flate' => 1], ['hex' => 1], - ['json' => 39], + ['json' => 40], ['lzw' => 2], ['pngpredictor' => 1], ['runlength' => 6], diff --git a/libqpdf/JSON.cc b/libqpdf/JSON.cc index 28f451a9..27405df7 100644 --- a/libqpdf/JSON.cc +++ b/libqpdf/JSON.cc @@ -628,6 +628,7 @@ namespace ls_number_e_sign, ls_alpha, ls_string, + ls_after_string, ls_backslash, ls_u4, ls_begin_array, @@ -1039,7 +1040,7 @@ JSONParser::getToken() "JSON: offset " + std::to_string(high_offset) + ": UTF-16 high surrogate not followed by low surrogate"); } - ignore(); + ignore(ls_after_string); return; } else if (*p == '\\') { ignore(ls_backslash); @@ -1234,7 +1235,7 @@ JSONParser::handleToken() } break; - case ls_string: + case ls_after_string: if (parser_state == ps_dict_begin || parser_state == ps_dict_after_comma) { dict_key = token; dict_key_offset = token_start; diff --git a/libtests/json.cc b/libtests/json.cc index e84ef0a0..4f4cff8e 100644 --- a/libtests/json.cc +++ b/libtests/json.cc @@ -134,6 +134,12 @@ test_main() " \"normal\": \"string\"\n" "}"); + try { + JSON::parse("\""); + assert(false); + } catch (std::runtime_error&) { + } + // Check default constructed JSON object (order as per JSON.hh). JSON uninitialized; std::string ws;