Commit 126dd31cad27991d40805df9582d5546464310c1
1 parent
6748bd33
In JSONParser combine stacks
Showing
1 changed file
with
20 additions
and
12 deletions
libqpdf/JSON.cc
| ... | ... | @@ -661,6 +661,18 @@ namespace |
| 661 | 661 | ls_comma, |
| 662 | 662 | }; |
| 663 | 663 | |
| 664 | + struct StackFrame | |
| 665 | + { | |
| 666 | + StackFrame(parser_state_e state, std::shared_ptr<JSON>& item) : | |
| 667 | + state(state), | |
| 668 | + item(item) | |
| 669 | + { | |
| 670 | + } | |
| 671 | + | |
| 672 | + parser_state_e state; | |
| 673 | + std::shared_ptr<JSON> item; | |
| 674 | + }; | |
| 675 | + | |
| 664 | 676 | InputSource& is; |
| 665 | 677 | JSON::Reactor* reactor; |
| 666 | 678 | lex_state_e lex_state; |
| ... | ... | @@ -673,8 +685,7 @@ namespace |
| 673 | 685 | std::string token; |
| 674 | 686 | qpdf_offset_t token_start{0}; |
| 675 | 687 | parser_state_e parser_state; |
| 676 | - std::vector<std::shared_ptr<JSON>> stack; | |
| 677 | - std::vector<parser_state_e> ps_stack; | |
| 688 | + std::vector<StackFrame> stack; | |
| 678 | 689 | std::string dict_key; |
| 679 | 690 | qpdf_offset_t dict_key_offset; |
| 680 | 691 | }; |
| ... | ... | @@ -1137,7 +1148,7 @@ JSONParser::handleToken() |
| 1137 | 1148 | |
| 1138 | 1149 | std::string s_value; |
| 1139 | 1150 | std::shared_ptr<JSON> item; |
| 1140 | - auto tos = stack.empty() ? nullptr : stack.back(); | |
| 1151 | + auto tos = stack.empty() ? nullptr : stack.back().item; | |
| 1141 | 1152 | auto ls = lex_state; |
| 1142 | 1153 | lex_state = ls_top; |
| 1143 | 1154 | |
| ... | ... | @@ -1186,8 +1197,7 @@ JSONParser::handleToken() |
| 1186 | 1197 | "JSON: offset " + std::to_string(offset) + |
| 1187 | 1198 | ": unexpected array end delimiter"); |
| 1188 | 1199 | } |
| 1189 | - parser_state = ps_stack.back(); | |
| 1190 | - ps_stack.pop_back(); | |
| 1200 | + parser_state = stack.back().state; | |
| 1191 | 1201 | tos->setEnd(offset); |
| 1192 | 1202 | if (reactor) { |
| 1193 | 1203 | reactor->containerEnd(*tos); |
| ... | ... | @@ -1205,8 +1215,7 @@ JSONParser::handleToken() |
| 1205 | 1215 | "JSON: offset " + std::to_string(offset) + |
| 1206 | 1216 | ": unexpected dictionary end delimiter"); |
| 1207 | 1217 | } |
| 1208 | - parser_state = ps_stack.back(); | |
| 1209 | - ps_stack.pop_back(); | |
| 1218 | + parser_state = stack.back().state; | |
| 1210 | 1219 | tos->setEnd(offset); |
| 1211 | 1220 | if (reactor) { |
| 1212 | 1221 | reactor->containerEnd(*tos); |
| ... | ... | @@ -1293,7 +1302,7 @@ JSONParser::handleToken() |
| 1293 | 1302 | |
| 1294 | 1303 | case ps_top: |
| 1295 | 1304 | if (!(item->isDictionary() || item->isArray())) { |
| 1296 | - stack.push_back(item); | |
| 1305 | + stack.push_back({ps_done, item}); | |
| 1297 | 1306 | parser_state = ps_done; |
| 1298 | 1307 | return; |
| 1299 | 1308 | } |
| ... | ... | @@ -1324,8 +1333,7 @@ JSONParser::handleToken() |
| 1324 | 1333 | } |
| 1325 | 1334 | |
| 1326 | 1335 | if (item->isDictionary() || item->isArray()) { |
| 1327 | - stack.push_back(item); | |
| 1328 | - ps_stack.push_back(parser_state); | |
| 1336 | + stack.push_back({parser_state, item}); | |
| 1329 | 1337 | // Calling container start method is postponed until after |
| 1330 | 1338 | // adding the containers to their parent containers, if any. |
| 1331 | 1339 | // This makes it much easier to keep track of the current |
| ... | ... | @@ -1342,7 +1350,7 @@ JSONParser::handleToken() |
| 1342 | 1350 | parser_state = ps_array_begin; |
| 1343 | 1351 | } |
| 1344 | 1352 | |
| 1345 | - if (ps_stack.size() > 500) { | |
| 1353 | + if (stack.size() > 500) { | |
| 1346 | 1354 | throw std::runtime_error( |
| 1347 | 1355 | "JSON: offset " + std::to_string(offset) + |
| 1348 | 1356 | ": maximum object depth exceeded"); |
| ... | ... | @@ -1361,7 +1369,7 @@ JSONParser::parse() |
| 1361 | 1369 | QTC::TC("libtests", "JSON parse premature EOF"); |
| 1362 | 1370 | throw std::runtime_error("JSON: premature end of input"); |
| 1363 | 1371 | } |
| 1364 | - auto const& tos = stack.back(); | |
| 1372 | + auto const& tos = stack.back().item; | |
| 1365 | 1373 | if (reactor && tos.get() && !(tos->isArray() || tos->isDictionary())) { |
| 1366 | 1374 | reactor->topLevelScalar(); |
| 1367 | 1375 | } | ... | ... |