Commit b1b789df4203296a848fec6a3513f30efceb1a45

Authored by Jay Berkenbilt
1 parent 3490090f

Detect end of input inside an unfinished JSON string

fuzz/json_fuzzer_seed_corpus/9bc1baa450a0977fb3ac06c1ddb3fc2d4c05a5ce 0 → 100644
  1 +{"qpdf":[{},{"obj:1 0 R":{"stream":{"data":"
0 2 \ No newline at end of file
... ...
fuzz/qtest/fuzz.test
... ... @@ -16,7 +16,7 @@ my @fuzzers = (
16 16 ['dct' => 1],
17 17 ['flate' => 1],
18 18 ['hex' => 1],
19   - ['json' => 39],
  19 + ['json' => 40],
20 20 ['lzw' => 2],
21 21 ['pngpredictor' => 1],
22 22 ['runlength' => 6],
... ...
libqpdf/JSON.cc
... ... @@ -628,6 +628,7 @@ namespace
628 628 ls_number_e_sign,
629 629 ls_alpha,
630 630 ls_string,
  631 + ls_after_string,
631 632 ls_backslash,
632 633 ls_u4,
633 634 ls_begin_array,
... ... @@ -1039,7 +1040,7 @@ JSONParser::getToken()
1039 1040 "JSON: offset " + std::to_string(high_offset) +
1040 1041 ": UTF-16 high surrogate not followed by low surrogate");
1041 1042 }
1042   - ignore();
  1043 + ignore(ls_after_string);
1043 1044 return;
1044 1045 } else if (*p == '\\') {
1045 1046 ignore(ls_backslash);
... ... @@ -1234,7 +1235,7 @@ JSONParser::handleToken()
1234 1235 }
1235 1236 break;
1236 1237  
1237   - case ls_string:
  1238 + case ls_after_string:
1238 1239 if (parser_state == ps_dict_begin || parser_state == ps_dict_after_comma) {
1239 1240 dict_key = token;
1240 1241 dict_key_offset = token_start;
... ...
libtests/json.cc
... ... @@ -134,6 +134,12 @@ test_main()
134 134 " \"normal\": \"string\"\n"
135 135 "}");
136 136  
  137 + try {
  138 + JSON::parse("\"");
  139 + assert(false);
  140 + } catch (std::runtime_error&) {
  141 + }
  142 +
137 143 // Check default constructed JSON object (order as per JSON.hh).
138 144 JSON uninitialized;
139 145 std::string ws;
... ...