Commit 35b1e1c4936903ebb841ed89945ea55fe95e0abb

Authored by Jay Berkenbilt
1 parent dc8df962

Explicitly test ignoring unknown keys in JSON input

... ... @@ -97,6 +97,9 @@ General things to remember:
97 97  
98 98 * Add json to the large file tests.
99 99  
  100 +* Document that keys other than "qpdf-v2" are ignored so people can
  101 + stash their own stuff.
  102 +
100 103 JSON to PDF:
101 104  
102 105 Have --json-input and --update-from-json. With --json-input, the json
... ...
libqpdf/QPDF_json.cc
... ... @@ -170,7 +170,7 @@ QPDF::JSONReactor::containerEnd(JSON const& value)
170 170 }
171 171 } else if (state == st_objects) {
172 172 if (parse_error) {
173   - // ignore
  173 + QTC::TC("qpdf", "QPDF_json don't check object after parse error");
174 174 } else if (cur_object == "trailer") {
175 175 if (!saw_value) {
176 176 QTC::TC("qpdf", "QPDF_json trailer no value");
... ... @@ -279,9 +279,9 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
279 279 this->saw_qpdf = true;
280 280 nestedState(key, value, st_qpdf);
281 281 } else {
282   - // Ignore all other fields for forward compatibility.
283   - // Don't use nestedState since this can be any type.
284   - // QXXXQ QTC
  282 + // Ignore all other fields. We explicitly allow people to
  283 + // add other top-level keys for their own use.
  284 + QTC::TC("qpdf", "QPDF_json ignoring unknown top-level key");
285 285 next_state = st_ignore;
286 286 }
287 287 } else if (state == st_qpdf) {
... ... @@ -304,8 +304,9 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
304 304 this->saw_objects = true;
305 305 nestedState(key, value, st_objects);
306 306 } else {
307   - // ignore unknown keys for forward compatibility
308   - // QXXXQ QTC
  307 + // ignore unknown keys for forward compatibility and to
  308 + // skip keys we don't care about like "maxobjectid".
  309 + QTC::TC("qpdf", "QPDF_json ignore second-level key");
309 310 next_state = st_ignore;
310 311 }
311 312 } else if (state == st_objects) {
... ... @@ -351,7 +352,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
351 352 }
352 353 } else {
353 354 // Ignore unknown keys for forward compatibility
354   - // QXXXQ QTC
  355 + QTC::TC("qpdf", "QPDF_json ignore unknown key in object_top");
355 356 next_state = st_ignore;
356 357 }
357 358 if (replacement.isInitialized()) {
... ... @@ -373,7 +374,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
373 374 parse_error = true;
374 375 } else {
375 376 // Ignore unknown keys for forward compatibility
376   - // QXXXQ QTC
  377 + QTC::TC("qpdf", "QPDF_json ignore unknown key in trailer");
377 378 next_state = st_ignore;
378 379 }
379 380 } else if (state == st_stream) {
... ... @@ -430,7 +431,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
430 431 }
431 432 } else {
432 433 // Ignore unknown keys for forward compatibility.
433   - // QXXXQ QTC
  434 + QTC::TC("qpdf", "QPDF_json ignore unknown key in stream");
434 435 next_state = st_ignore;
435 436 }
436 437 } else if (state == st_object) {
... ... @@ -549,12 +550,6 @@ QPDF::importJSON(std::shared_ptr<InputSource> is, bool must_be_complete)
549 550 if (reactor.anyErrors()) {
550 551 throw std::runtime_error(is->getName() + ": errors found in JSON");
551 552 }
552   - // QXXXQ
553   - // std::cout << "trailer:\n" << getTrailer().unparse() << std::endl;
554   - // for (auto& oh: getAllObjects()) {
555   - // std::cout << oh.unparse() << ":" << std::endl;
556   - // std::cout << oh.unparseResolved() << std::endl;
557   - // }
558 553 }
559 554  
560 555 void
... ...
qpdf/qpdf.testcov
... ... @@ -669,3 +669,9 @@ QPDF_json value stream both or neither 0
669 669 QPDFJob need json-stream-prefix for stdout 0
670 670 QPDFJob write json to stdout 0
671 671 QPDFJob write json to file 0
  672 +QPDF_json don't check object after parse error 0
  673 +QPDF_json ignoring unknown top-level key 0
  674 +QPDF_json ignore second-level key 0
  675 +QPDF_json ignore unknown key in object_top 0
  676 +QPDF_json ignore unknown key in trailer 0
  677 +QPDF_json ignore unknown key in stream 0
... ...
qpdf/qtest/qpdf/manual-qpdf-json.json
1 1 {
  2 + "comment": [
  3 + "We allow and ignore other top-level keys"
  4 + ],
2 5 "qpdf-v2": {
3 6 "pdfversion": "2.0",
  7 + "maybe-future-key": {
  8 + "x": [
  9 + "Lots of times we ignore things",
  10 + "for forward-compatibility so we don't have",
  11 + "to change the version number if we add stuff",
  12 + "in the future"
  13 + ]
  14 + },
4 15 "objects": {
5 16 "obj:3 0 R": {
6 17 "value": {
... ... @@ -19,7 +30,8 @@
19 30 "/ProcSet": "5 0 R"
20 31 },
21 32 "/Type": "/Page"
22   - }
  33 + },
  34 + "ignore": "this is ignored"
23 35 },
24 36 "obj:2 0 R": {
25 37 "value": {
... ... @@ -28,6 +40,10 @@
28 40 "3 0 R"
29 41 ],
30 42 "/Type": "/Pages"
  43 + },
  44 + "ignore": {
  45 + "potato": "salad",
  46 + "this": ["is ignored too"]
31 47 }
32 48 },
33 49 "obj:1 0 R": {
... ... @@ -38,6 +54,7 @@
38 54 },
39 55 "obj:4 0 R": {
40 56 "stream": {
  57 + "what-is-this": "doesn't matter",
41 58 "dict": {},
42 59 "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo="
43 60 }
... ... @@ -58,6 +75,7 @@
58 75 }
59 76 },
60 77 "trailer": {
  78 + "even-here-we-ignore": "stuff",
61 79 "value": {
62 80 "/QTest": "7 0 R",
63 81 "/Root": "1 0 R",
... ...