2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-10-31 19:02:30 +00:00

In JSONParser::handleToken avoid creating JSON objects for dictionary keys

This commit is contained in:
m-holger 2023-01-27 13:35:02 +00:00
parent f2e46c20b6
commit a39043f65e

View File

@ -1138,8 +1138,10 @@ JSONParser::handleToken()
std::string s_value; std::string s_value;
std::shared_ptr<JSON> item; std::shared_ptr<JSON> item;
auto tos = stack.empty() ? nullptr : stack.back(); auto tos = stack.empty() ? nullptr : stack.back();
auto ls = lex_state;
lex_state = ls_top;
switch (lex_state) { switch (ls) {
case ls_begin_dict: case ls_begin_dict:
item = std::make_shared<JSON>(JSON::makeDictionary()); item = std::make_shared<JSON>(JSON::makeDictionary());
break; break;
@ -1156,7 +1158,6 @@ JSONParser::handleToken()
": unexpected colon"); ": unexpected colon");
} }
parser_state = ps_dict_after_colon; parser_state = ps_dict_after_colon;
lex_state = ls_top;
return; return;
case ls_comma: case ls_comma:
@ -1175,7 +1176,6 @@ JSONParser::handleToken()
throw std::logic_error("JSONParser::handleToken: unexpected parser" throw std::logic_error("JSONParser::handleToken: unexpected parser"
" state for comma"); " state for comma");
} }
lex_state = ls_top;
return; return;
case ls_end_array: case ls_end_array:
@ -1195,7 +1195,6 @@ JSONParser::handleToken()
if (parser_state != ps_done) { if (parser_state != ps_done) {
stack.pop_back(); stack.pop_back();
} }
lex_state = ls_top;
return; return;
case ls_end_dict: case ls_end_dict:
@ -1215,7 +1214,6 @@ JSONParser::handleToken()
if (parser_state != ps_done) { if (parser_state != ps_done) {
stack.pop_back(); stack.pop_back();
} }
lex_state = ls_top;
return; return;
case ls_number: case ls_number:
@ -1243,7 +1241,15 @@ JSONParser::handleToken()
throw std::logic_error("JSON string length < 2"); throw std::logic_error("JSON string length < 2");
} }
s_value = decode_string(token, token_start); s_value = decode_string(token, token_start);
item = std::make_shared<JSON>(JSON::makeString(s_value)); if (parser_state == ps_dict_begin ||
parser_state == ps_dict_after_comma) {
dict_key = s_value;
dict_key_offset = token_start;
parser_state = ps_dict_after_key;
return;
} else {
item = std::make_shared<JSON>(JSON::makeString(s_value));
}
break; break;
default: default:
@ -1260,16 +1266,10 @@ JSONParser::handleToken()
switch (parser_state) { switch (parser_state) {
case ps_dict_begin: case ps_dict_begin:
case ps_dict_after_comma: case ps_dict_after_comma:
if (lex_state != ls_string) { QTC::TC("libtests", "JSON parse string as dict key");
QTC::TC("libtests", "JSON parse string as dict key"); throw std::runtime_error(
throw std::runtime_error( "JSON: offset " + std::to_string(offset) +
"JSON: offset " + std::to_string(offset) + ": expect string as dictionary key");
": expect string as dictionary key");
}
this->dict_key = s_value;
this->dict_key_offset = item->getStart();
item = nullptr;
next_state = ps_dict_after_key;
break; break;
case ps_dict_after_colon: case ps_dict_after_colon:
@ -1320,7 +1320,7 @@ JSONParser::handleToken()
"JSONParser::handleToken: unexpected parser state"); "JSONParser::handleToken: unexpected parser state");
} }
if (reactor && item.get()) { if (reactor) {
// Calling container start method is postponed until after // Calling container start method is postponed until after
// adding the containers to their parent containers, if any. // adding the containers to their parent containers, if any.
// This makes it much easier to keep track of the current // This makes it much easier to keep track of the current
@ -1333,26 +1333,25 @@ JSONParser::handleToken()
} }
// Prepare for next token // Prepare for next token
if (item.get()) {
if (item->isDictionary()) { if (item->isDictionary()) {
stack.push_back(item); stack.push_back(item);
ps_stack.push_back(next_state); ps_stack.push_back(next_state);
next_state = ps_dict_begin; next_state = ps_dict_begin;
} else if (item->isArray()) { } else if (item->isArray()) {
stack.push_back(item); stack.push_back(item);
ps_stack.push_back(next_state); ps_stack.push_back(next_state);
next_state = ps_array_begin; next_state = ps_array_begin;
} else if (parser_state == ps_top) { } else if (parser_state == ps_top) {
stack.push_back(item); stack.push_back(item);
}
} }
if (ps_stack.size() > 500) { if (ps_stack.size() > 500) {
throw std::runtime_error( throw std::runtime_error(
"JSON: offset " + std::to_string(offset) + "JSON: offset " + std::to_string(offset) +
": maximum object depth exceeded"); ": maximum object depth exceeded");
} }
parser_state = next_state; parser_state = next_state;
lex_state = ls_top;
} }
std::shared_ptr<JSON> std::shared_ptr<JSON>