Commit a39043f65eebdc24d98bdc29160ad489222c4ec3

Authored by m-holger
1 parent f2e46c20

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

Showing 1 changed file with 29 additions and 30 deletions
libqpdf/JSON.cc
... ... @@ -1138,8 +1138,10 @@ JSONParser::handleToken()
1138 1138 std::string s_value;
1139 1139 std::shared_ptr<JSON> item;
1140 1140 auto tos = stack.empty() ? nullptr : stack.back();
  1141 + auto ls = lex_state;
  1142 + lex_state = ls_top;
1141 1143  
1142   - switch (lex_state) {
  1144 + switch (ls) {
1143 1145 case ls_begin_dict:
1144 1146 item = std::make_shared<JSON>(JSON::makeDictionary());
1145 1147 break;
... ... @@ -1156,7 +1158,6 @@ JSONParser::handleToken()
1156 1158 ": unexpected colon");
1157 1159 }
1158 1160 parser_state = ps_dict_after_colon;
1159   - lex_state = ls_top;
1160 1161 return;
1161 1162  
1162 1163 case ls_comma:
... ... @@ -1175,7 +1176,6 @@ JSONParser::handleToken()
1175 1176 throw std::logic_error("JSONParser::handleToken: unexpected parser"
1176 1177 " state for comma");
1177 1178 }
1178   - lex_state = ls_top;
1179 1179 return;
1180 1180  
1181 1181 case ls_end_array:
... ... @@ -1195,7 +1195,6 @@ JSONParser::handleToken()
1195 1195 if (parser_state != ps_done) {
1196 1196 stack.pop_back();
1197 1197 }
1198   - lex_state = ls_top;
1199 1198 return;
1200 1199  
1201 1200 case ls_end_dict:
... ... @@ -1215,7 +1214,6 @@ JSONParser::handleToken()
1215 1214 if (parser_state != ps_done) {
1216 1215 stack.pop_back();
1217 1216 }
1218   - lex_state = ls_top;
1219 1217 return;
1220 1218  
1221 1219 case ls_number:
... ... @@ -1243,7 +1241,15 @@ JSONParser::handleToken()
1243 1241 throw std::logic_error("JSON string length < 2");
1244 1242 }
1245 1243 s_value = decode_string(token, token_start);
1246   - item = std::make_shared<JSON>(JSON::makeString(s_value));
  1244 + if (parser_state == ps_dict_begin ||
  1245 + parser_state == ps_dict_after_comma) {
  1246 + dict_key = s_value;
  1247 + dict_key_offset = token_start;
  1248 + parser_state = ps_dict_after_key;
  1249 + return;
  1250 + } else {
  1251 + item = std::make_shared<JSON>(JSON::makeString(s_value));
  1252 + }
1247 1253 break;
1248 1254  
1249 1255 default:
... ... @@ -1260,16 +1266,10 @@ JSONParser::handleToken()
1260 1266 switch (parser_state) {
1261 1267 case ps_dict_begin:
1262 1268 case ps_dict_after_comma:
1263   - if (lex_state != ls_string) {
1264   - QTC::TC("libtests", "JSON parse string as dict key");
1265   - throw std::runtime_error(
1266   - "JSON: offset " + std::to_string(offset) +
1267   - ": expect string as dictionary key");
1268   - }
1269   - this->dict_key = s_value;
1270   - this->dict_key_offset = item->getStart();
1271   - item = nullptr;
1272   - next_state = ps_dict_after_key;
  1269 + QTC::TC("libtests", "JSON parse string as dict key");
  1270 + throw std::runtime_error(
  1271 + "JSON: offset " + std::to_string(offset) +
  1272 + ": expect string as dictionary key");
1273 1273 break;
1274 1274  
1275 1275 case ps_dict_after_colon:
... ... @@ -1320,7 +1320,7 @@ JSONParser::handleToken()
1320 1320 "JSONParser::handleToken: unexpected parser state");
1321 1321 }
1322 1322  
1323   - if (reactor && item.get()) {
  1323 + if (reactor) {
1324 1324 // Calling container start method is postponed until after
1325 1325 // adding the containers to their parent containers, if any.
1326 1326 // This makes it much easier to keep track of the current
... ... @@ -1333,26 +1333,25 @@ JSONParser::handleToken()
1333 1333 }
1334 1334  
1335 1335 // Prepare for next token
1336   - if (item.get()) {
1337   - if (item->isDictionary()) {
1338   - stack.push_back(item);
1339   - ps_stack.push_back(next_state);
1340   - next_state = ps_dict_begin;
1341   - } else if (item->isArray()) {
1342   - stack.push_back(item);
1343   - ps_stack.push_back(next_state);
1344   - next_state = ps_array_begin;
1345   - } else if (parser_state == ps_top) {
1346   - stack.push_back(item);
1347   - }
  1336 +
  1337 + if (item->isDictionary()) {
  1338 + stack.push_back(item);
  1339 + ps_stack.push_back(next_state);
  1340 + next_state = ps_dict_begin;
  1341 + } else if (item->isArray()) {
  1342 + stack.push_back(item);
  1343 + ps_stack.push_back(next_state);
  1344 + next_state = ps_array_begin;
  1345 + } else if (parser_state == ps_top) {
  1346 + stack.push_back(item);
1348 1347 }
  1348 +
1349 1349 if (ps_stack.size() > 500) {
1350 1350 throw std::runtime_error(
1351 1351 "JSON: offset " + std::to_string(offset) +
1352 1352 ": maximum object depth exceeded");
1353 1353 }
1354 1354 parser_state = next_state;
1355   - lex_state = ls_top;
1356 1355 }
1357 1356  
1358 1357 std::shared_ptr<JSON>
... ...