2
1
mirror of https://github.com/qpdf/qpdf.git synced 2025-01-05 16:12:13 +00:00

In JSONParser combine stacks

This commit is contained in:
m-holger 2023-01-27 14:37:25 +00:00
parent 6748bd33f7
commit 126dd31cad

View File

@ -661,6 +661,18 @@ namespace
ls_comma, ls_comma,
}; };
struct StackFrame
{
StackFrame(parser_state_e state, std::shared_ptr<JSON>& item) :
state(state),
item(item)
{
}
parser_state_e state;
std::shared_ptr<JSON> item;
};
InputSource& is; InputSource& is;
JSON::Reactor* reactor; JSON::Reactor* reactor;
lex_state_e lex_state; lex_state_e lex_state;
@ -673,8 +685,7 @@ namespace
std::string token; std::string token;
qpdf_offset_t token_start{0}; qpdf_offset_t token_start{0};
parser_state_e parser_state; parser_state_e parser_state;
std::vector<std::shared_ptr<JSON>> stack; std::vector<StackFrame> stack;
std::vector<parser_state_e> ps_stack;
std::string dict_key; std::string dict_key;
qpdf_offset_t dict_key_offset; qpdf_offset_t dict_key_offset;
}; };
@ -1137,7 +1148,7 @@ 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().item;
auto ls = lex_state; auto ls = lex_state;
lex_state = ls_top; lex_state = ls_top;
@ -1186,8 +1197,7 @@ JSONParser::handleToken()
"JSON: offset " + std::to_string(offset) + "JSON: offset " + std::to_string(offset) +
": unexpected array end delimiter"); ": unexpected array end delimiter");
} }
parser_state = ps_stack.back(); parser_state = stack.back().state;
ps_stack.pop_back();
tos->setEnd(offset); tos->setEnd(offset);
if (reactor) { if (reactor) {
reactor->containerEnd(*tos); reactor->containerEnd(*tos);
@ -1205,8 +1215,7 @@ JSONParser::handleToken()
"JSON: offset " + std::to_string(offset) + "JSON: offset " + std::to_string(offset) +
": unexpected dictionary end delimiter"); ": unexpected dictionary end delimiter");
} }
parser_state = ps_stack.back(); parser_state = stack.back().state;
ps_stack.pop_back();
tos->setEnd(offset); tos->setEnd(offset);
if (reactor) { if (reactor) {
reactor->containerEnd(*tos); reactor->containerEnd(*tos);
@ -1293,7 +1302,7 @@ JSONParser::handleToken()
case ps_top: case ps_top:
if (!(item->isDictionary() || item->isArray())) { if (!(item->isDictionary() || item->isArray())) {
stack.push_back(item); stack.push_back({ps_done, item});
parser_state = ps_done; parser_state = ps_done;
return; return;
} }
@ -1324,8 +1333,7 @@ JSONParser::handleToken()
} }
if (item->isDictionary() || item->isArray()) { if (item->isDictionary() || item->isArray()) {
stack.push_back(item); stack.push_back({parser_state, item});
ps_stack.push_back(parser_state);
// 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
@ -1342,7 +1350,7 @@ JSONParser::handleToken()
parser_state = ps_array_begin; parser_state = ps_array_begin;
} }
if (ps_stack.size() > 500) { if (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");
@ -1361,7 +1369,7 @@ JSONParser::parse()
QTC::TC("libtests", "JSON parse premature EOF"); QTC::TC("libtests", "JSON parse premature EOF");
throw std::runtime_error("JSON: premature end of input"); throw std::runtime_error("JSON: premature end of input");
} }
auto const& tos = stack.back(); auto const& tos = stack.back().item;
if (reactor && tos.get() && !(tos->isArray() || tos->isDictionary())) { if (reactor && tos.get() && !(tos->isArray() || tos->isDictionary())) {
reactor->topLevelScalar(); reactor->topLevelScalar();
} }