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,8 +1138,10 @@ JSONParser::handleToken()
1138 std::string s_value; 1138 std::string s_value;
1139 std::shared_ptr<JSON> item; 1139 std::shared_ptr<JSON> item;
1140 auto tos = stack.empty() ? nullptr : stack.back(); 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 case ls_begin_dict: 1145 case ls_begin_dict:
1144 item = std::make_shared<JSON>(JSON::makeDictionary()); 1146 item = std::make_shared<JSON>(JSON::makeDictionary());
1145 break; 1147 break;
@@ -1156,7 +1158,6 @@ JSONParser::handleToken() @@ -1156,7 +1158,6 @@ JSONParser::handleToken()
1156 ": unexpected colon"); 1158 ": unexpected colon");
1157 } 1159 }
1158 parser_state = ps_dict_after_colon; 1160 parser_state = ps_dict_after_colon;
1159 - lex_state = ls_top;  
1160 return; 1161 return;
1161 1162
1162 case ls_comma: 1163 case ls_comma:
@@ -1175,7 +1176,6 @@ JSONParser::handleToken() @@ -1175,7 +1176,6 @@ JSONParser::handleToken()
1175 throw std::logic_error("JSONParser::handleToken: unexpected parser" 1176 throw std::logic_error("JSONParser::handleToken: unexpected parser"
1176 " state for comma"); 1177 " state for comma");
1177 } 1178 }
1178 - lex_state = ls_top;  
1179 return; 1179 return;
1180 1180
1181 case ls_end_array: 1181 case ls_end_array:
@@ -1195,7 +1195,6 @@ JSONParser::handleToken() @@ -1195,7 +1195,6 @@ JSONParser::handleToken()
1195 if (parser_state != ps_done) { 1195 if (parser_state != ps_done) {
1196 stack.pop_back(); 1196 stack.pop_back();
1197 } 1197 }
1198 - lex_state = ls_top;  
1199 return; 1198 return;
1200 1199
1201 case ls_end_dict: 1200 case ls_end_dict:
@@ -1215,7 +1214,6 @@ JSONParser::handleToken() @@ -1215,7 +1214,6 @@ JSONParser::handleToken()
1215 if (parser_state != ps_done) { 1214 if (parser_state != ps_done) {
1216 stack.pop_back(); 1215 stack.pop_back();
1217 } 1216 }
1218 - lex_state = ls_top;  
1219 return; 1217 return;
1220 1218
1221 case ls_number: 1219 case ls_number:
@@ -1243,7 +1241,15 @@ JSONParser::handleToken() @@ -1243,7 +1241,15 @@ JSONParser::handleToken()
1243 throw std::logic_error("JSON string length < 2"); 1241 throw std::logic_error("JSON string length < 2");
1244 } 1242 }
1245 s_value = decode_string(token, token_start); 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 break; 1253 break;
1248 1254
1249 default: 1255 default:
@@ -1260,16 +1266,10 @@ JSONParser::handleToken() @@ -1260,16 +1266,10 @@ JSONParser::handleToken()
1260 switch (parser_state) { 1266 switch (parser_state) {
1261 case ps_dict_begin: 1267 case ps_dict_begin:
1262 case ps_dict_after_comma: 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 break; 1273 break;
1274 1274
1275 case ps_dict_after_colon: 1275 case ps_dict_after_colon:
@@ -1320,7 +1320,7 @@ JSONParser::handleToken() @@ -1320,7 +1320,7 @@ JSONParser::handleToken()
1320 "JSONParser::handleToken: unexpected parser state"); 1320 "JSONParser::handleToken: unexpected parser state");
1321 } 1321 }
1322 1322
1323 - if (reactor && item.get()) { 1323 + if (reactor) {
1324 // Calling container start method is postponed until after 1324 // Calling container start method is postponed until after
1325 // adding the containers to their parent containers, if any. 1325 // adding the containers to their parent containers, if any.
1326 // This makes it much easier to keep track of the current 1326 // This makes it much easier to keep track of the current
@@ -1333,26 +1333,25 @@ JSONParser::handleToken() @@ -1333,26 +1333,25 @@ JSONParser::handleToken()
1333 } 1333 }
1334 1334
1335 // Prepare for next token 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 if (ps_stack.size() > 500) { 1349 if (ps_stack.size() > 500) {
1350 throw std::runtime_error( 1350 throw std::runtime_error(
1351 "JSON: offset " + std::to_string(offset) + 1351 "JSON: offset " + std::to_string(offset) +
1352 ": maximum object depth exceeded"); 1352 ": maximum object depth exceeded");
1353 } 1353 }
1354 parser_state = next_state; 1354 parser_state = next_state;
1355 - lex_state = ls_top;  
1356 } 1355 }
1357 1356
1358 std::shared_ptr<JSON> 1357 std::shared_ptr<JSON>