Commit 06001ed25b1f005a91d92104f2d7c47617809cd4

Authored by m-holger
Committed by m-holger
1 parent 87ee8ad0

Refactor the creation of unresolved objects

Create unresolved objects only for objects in the xref table (except during
parsing of the xref table). Do not add indirect nulls into the the object
cache as the result of a cache miss during a call to getObject except
during parsing or creation/updating from JSON. To support this behaviour,
add new private methods getObjectForParser and getObjectForJSON.

As a result of this change, dangling references are treated as direct nulls
rather than indirect nulls.
include/qpdf/QPDF.hh
... ... @@ -819,7 +819,8 @@ class QPDF
819 819 }
820 820 };
821 821  
822   - // The ParseGuard class allows QPDFParser to detect re-entrant parsing.
  822 + // The ParseGuard class allows QPDFParser to detect re-entrant parsing. It also provides
  823 + // special access to allow the parser to create unresolved objects and dangling references.
823 824 class ParseGuard
824 825 {
825 826 friend class QPDFParser;
... ... @@ -832,6 +833,13 @@ class QPDF
832 833 qpdf->inParse(true);
833 834 }
834 835 }
  836 +
  837 + static std::shared_ptr<QPDFObject>
  838 + getObject(QPDF* qpdf, int id, int gen, bool parse_pdf)
  839 + {
  840 + return qpdf->getObjectForParser(id, gen, parse_pdf);
  841 + }
  842 +
835 843 ~ParseGuard()
836 844 {
837 845 if (qpdf) {
... ... @@ -900,8 +908,8 @@ class QPDF
900 908 }
901 909 ObjCache(
902 910 std::shared_ptr<QPDFObject> object,
903   - qpdf_offset_t end_before_space,
904   - qpdf_offset_t end_after_space) :
  911 + qpdf_offset_t end_before_space = 0,
  912 + qpdf_offset_t end_after_space = 0) :
905 913 object(object),
906 914 end_before_space(end_before_space),
907 915 end_after_space(end_after_space)
... ... @@ -1065,13 +1073,14 @@ class QPDF
1065 1073 QPDFObject* resolve(QPDFObjGen og);
1066 1074 void resolveObjectsInStream(int obj_stream_number);
1067 1075 void stopOnError(std::string const& message);
1068   - QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);
1069 1076 QPDFObjectHandle reserveStream(QPDFObjGen const& og);
1070 1077 QPDFObjGen nextObjGen();
1071 1078 QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&);
1072 1079 QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj);
1073 1080 bool isCached(QPDFObjGen const& og);
1074 1081 bool isUnresolved(QPDFObjGen const& og);
  1082 + std::shared_ptr<QPDFObject> getObjectForParser(int id, int gen, bool parse_pdf);
  1083 + std::shared_ptr<QPDFObject> getObjectForJSON(int id, int gen);
1075 1084 void removeObject(QPDFObjGen og);
1076 1085 void updateCache(
1077 1086 QPDFObjGen const& og,
... ...
libqpdf/QPDF.cc
... ... @@ -654,9 +654,11 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
654 654 }
655 655 check_warnings();
656 656 if (!m->parsed) {
  657 + m->parsed = true;
657 658 getAllPages();
658 659 check_warnings();
659 660 if (m->all_pages.empty()) {
  661 + m->parsed = false;
660 662 throw damagedPDF("", 0, "unable to find any pages while recovering damaged file");
661 663 }
662 664 }
... ... @@ -2096,30 +2098,52 @@ QPDF::newStream(std::string const&amp; data)
2096 2098 }
2097 2099  
2098 2100 QPDFObjectHandle
2099   -QPDF::reserveObjectIfNotExists(QPDFObjGen const& og)
  2101 +QPDF::reserveStream(QPDFObjGen const& og)
2100 2102 {
2101   - if (!isCached(og) && m->xref_table.count(og) == 0) {
2102   - updateCache(og, QPDF_Reserved::create(), -1, -1);
2103   - return newIndirect(og, m->obj_cache[og].object);
2104   - } else {
2105   - return getObject(og);
  2103 + return {QPDF_Stream::create(this, og, QPDFObjectHandle::newDictionary(), 0, 0)};
  2104 +}
  2105 +
  2106 +std::shared_ptr<QPDFObject>
  2107 +QPDF::getObjectForParser(int id, int gen, bool parse_pdf)
  2108 +{
  2109 + // This method is called by the parser and therefore must not resolve any objects.
  2110 + auto og = QPDFObjGen(id, gen);
  2111 + if (auto iter = m->obj_cache.find(og); iter != m->obj_cache.end()) {
  2112 + return iter->second.object;
  2113 + }
  2114 + if (m->xref_table.count(og) || !m->parsed) {
  2115 + return m->obj_cache.insert({og, QPDF_Unresolved::create(this, og)}).first->second.object;
2106 2116 }
  2117 + if (parse_pdf) {
  2118 + return QPDF_Null::create();
  2119 + }
  2120 + return m->obj_cache.insert({og, QPDF_Null::create(this, og)}).first->second.object;
2107 2121 }
2108 2122  
2109   -QPDFObjectHandle
2110   -QPDF::reserveStream(QPDFObjGen const& og)
  2123 +std::shared_ptr<QPDFObject>
  2124 +QPDF::getObjectForJSON(int id, int gen)
2111 2125 {
2112   - return {QPDF_Stream::create(this, og, QPDFObjectHandle::newDictionary(), 0, 0)};
  2126 + auto og = QPDFObjGen(id, gen);
  2127 + auto [it, inserted] = m->obj_cache.try_emplace(og);
  2128 + auto& obj = it->second.object;
  2129 + if (inserted) {
  2130 + obj = (m->parsed && !m->xref_table.count(og)) ? QPDF_Null::create(this, og)
  2131 + : QPDF_Unresolved::create(this, og);
  2132 + }
  2133 + return obj;
2113 2134 }
2114 2135  
2115 2136 QPDFObjectHandle
2116 2137 QPDF::getObject(QPDFObjGen const& og)
2117 2138 {
2118   - // This method is called by the parser and therefore must not resolve any objects.
2119   - if (!isCached(og)) {
2120   - m->obj_cache[og] = ObjCache(QPDF_Unresolved::create(this, og), -1, -1);
  2139 + if (auto it = m->obj_cache.find(og); it != m->obj_cache.end()) {
  2140 + return {it->second.object};
  2141 + } else if (m->parsed && !m->xref_table.count(og)) {
  2142 + return QPDF_Null::create();
  2143 + } else {
  2144 + auto result = m->obj_cache.try_emplace(og, QPDF_Unresolved::create(this, og), -1, -1);
  2145 + return {result.first->second.object};
2121 2146 }
2122   - return newIndirect(og, m->obj_cache[og].object);
2123 2147 }
2124 2148  
2125 2149 QPDFObjectHandle
... ...
libqpdf/QPDFParser.cc
... ... @@ -166,10 +166,7 @@ QPDFParser::parseRemainder(bool content_stream)
166 166 auto id = QIntC::to_int(int_buffer[(int_count - 1) % 2]);
167 167 auto gen = QIntC::to_int(int_buffer[(int_count) % 2]);
168 168 if (!(id < 1 || gen < 0 || gen >= 65535)) {
169   - // This action has the desirable side effect of causing dangling references
170   - // (references to indirect objects that don't appear in the PDF) in any parsed
171   - // object to appear in the object cache.
172   - add(std::move(context->getObject(id, gen).obj));
  169 + add(QPDF::ParseGuard::getObject(context, id, gen, parse_pdf));
173 170 } else {
174 171 QTC::TC("qpdf", "QPDFParser invalid objgen");
175 172 addNull();
... ...
libqpdf/QPDFWriter.cc
... ... @@ -1237,7 +1237,7 @@ bool
1237 1237 QPDFWriter::willFilterStream(
1238 1238 QPDFObjectHandle stream,
1239 1239 bool& compress_stream, // out only
1240   - bool& is_metadata, // out only
  1240 + bool& is_metadata, // out only
1241 1241 std::shared_ptr<Buffer>* stream_data)
1242 1242 {
1243 1243 compress_stream = false;
... ...
libqpdf/QPDF_Null.cc
... ... @@ -3,15 +3,15 @@
3 3 #include <qpdf/JSON_writer.hh>
4 4 #include <qpdf/QPDFObject_private.hh>
5 5  
6   -QPDF_Null::QPDF_Null() :
7   - QPDFValue(::ot_null, "null")
  6 +QPDF_Null::QPDF_Null(QPDF* qpdf, QPDFObjGen og) :
  7 + QPDFValue(::ot_null, "null", qpdf, og)
8 8 {
9 9 }
10 10  
11 11 std::shared_ptr<QPDFObject>
12   -QPDF_Null::create()
  12 +QPDF_Null::create(QPDF* qpdf, QPDFObjGen og)
13 13 {
14   - return do_create(new QPDF_Null());
  14 + return do_create(new QPDF_Null(qpdf, og));
15 15 }
16 16  
17 17 std::shared_ptr<QPDFObject>
... ...
libqpdf/QPDF_json.cc
... ... @@ -240,11 +240,6 @@ class QPDF::JSONReactor: public JSON::Reactor
240 240 descr(std::make_shared<QPDFValue::Description>(
241 241 QPDFValue::JSON_Descr(std::make_shared<std::string>(is->getName()), "")))
242 242 {
243   - for (auto& oc: pdf.m->obj_cache) {
244   - if (oc.second.object->getTypeCode() == ::ot_reserved) {
245   - reserved.insert(oc.first);
246   - }
247   - }
248 243 }
249 244 ~JSONReactor() override = default;
250 245 void dictionaryStart() override;
... ... @@ -305,7 +300,6 @@ class QPDF::JSONReactor: public JSON::Reactor
305 300 bool saw_data{false};
306 301 bool saw_datafile{false};
307 302 bool this_stream_needs_data{false};
308   - std::set<QPDFObjGen> reserved;
309 303 std::vector<StackFrame> stack;
310 304 QPDFObjectHandle next_obj;
311 305 state_e next_state{st_top};
... ... @@ -416,16 +410,6 @@ QPDF::JSONReactor::containerEnd(JSON const&amp; value)
416 410 }
417 411 }
418 412 }
419   - } else if (from_state == st_qpdf) {
420   - // Handle dangling indirect object references which the PDF spec says to treat as nulls.
421   - // It's tempting to make this an error, but that would be wrong since valid input files may
422   - // have these.
423   - for (auto& oc: pdf.m->obj_cache) {
424   - if (oc.second.object->getTypeCode() == ::ot_reserved && reserved.count(oc.first) == 0) {
425   - QTC::TC("qpdf", "QPDF_json non-trivial null reserved");
426   - pdf.updateCache(oc.first, QPDF_Null::create(), -1, -1);
427   - }
428   - }
429 413 }
430 414 if (!stack.empty()) {
431 415 auto state = stack.back().state;
... ... @@ -565,7 +549,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
565 549 } else if (is_obj_key(key, obj, gen)) {
566 550 this->cur_object = key;
567 551 if (setNextStateIfDictionary(key, value, st_object_top)) {
568   - next_obj = pdf.reserveObjectIfNotExists(QPDFObjGen(obj, gen));
  552 + next_obj = pdf.getObjectForJSON(obj, gen);
569 553 }
570 554 } else {
571 555 QTC::TC("qpdf", "QPDF_json bad object key");
... ... @@ -767,7 +751,7 @@ QPDF::JSONReactor::makeObject(JSON const&amp; value)
767 751 int gen = 0;
768 752 std::string str;
769 753 if (is_indirect_object(str_v, obj, gen)) {
770   - result = pdf.reserveObjectIfNotExists(QPDFObjGen(obj, gen));
  754 + result = pdf.getObjectForJSON(obj, gen);
771 755 } else if (is_unicode_string(str_v, str)) {
772 756 result = QPDFObjectHandle::newUnicodeString(str);
773 757 } else if (is_binary_string(str_v, str)) {
... ...
libqpdf/qpdf/QPDFParser.hh
... ... @@ -24,7 +24,8 @@ class QPDFParser
24 24 decrypter(decrypter),
25 25 context(context),
26 26 description(std::make_shared<QPDFValue::Description>(
27   - std::string(input->getName() + ", " + object_description + " at offset $PO")))
  27 + std::string(input->getName() + ", " + object_description + " at offset $PO"))),
  28 + parse_pdf(parse_pdf)
28 29 {
29 30 }
30 31 virtual ~QPDFParser() = default;
... ... @@ -77,6 +78,8 @@ class QPDFParser
77 78 QPDFObjectHandle::StringDecrypter* decrypter;
78 79 QPDF* context;
79 80 std::shared_ptr<QPDFValue::Description> description;
  81 + bool parse_pdf;
  82 +
80 83 std::vector<StackFrame> stack;
81 84 StackFrame* frame;
82 85 // Number of recent bad tokens.
... ...
libqpdf/qpdf/QPDF_Null.hh
... ... @@ -7,7 +7,7 @@ class QPDF_Null: public QPDFValue
7 7 {
8 8 public:
9 9 ~QPDF_Null() override = default;
10   - static std::shared_ptr<QPDFObject> create();
  10 + static std::shared_ptr<QPDFObject> create(QPDF* qpdf = nullptr, QPDFObjGen og = QPDFObjGen());
11 11 static std::shared_ptr<QPDFObject> create(
12 12 std::shared_ptr<QPDFObject> parent,
13 13 std::string_view const& static_descr,
... ... @@ -21,7 +21,7 @@ class QPDF_Null: public QPDFValue
21 21 void writeJSON(int json_version, JSON::Writer& p) override;
22 22  
23 23 private:
24   - QPDF_Null();
  24 + QPDF_Null(QPDF* qpdf = nullptr, QPDFObjGen og = QPDFObjGen());
25 25 };
26 26  
27 27 #endif // QPDF_NULL_HH
... ...
libtests/sparse_array.cc
... ... @@ -90,17 +90,17 @@ main()
90 90  
91 91 obj = QPDF_Array::create({10, "null"_qpdf.getObj()}, true);
92 92 QPDF_Array& b = *obj->as<QPDF_Array>();
93   - b.setAt(5, pdf.getObject(5, 0));
  93 + b.setAt(5, pdf.newIndirectNull());
94 94 b.setAt(7, "[0 1 2 3]"_qpdf);
95 95 assert(b.at(3).isNull());
96 96 assert(b.at(8).isNull());
97 97 assert(b.at(5).isIndirect());
98   - assert(b.unparse() == "[ null null null null null 5 0 R null [ 0 1 2 3 ] null null ]");
  98 + assert(b.unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]");
99 99 auto c = b.copy(true);
100 100 auto d = b.copy(false);
101 101 b.at(7).setArrayItem(2, "42"_qpdf);
102   - assert(c->unparse() == "[ null null null null null 5 0 R null [ 0 1 42 3 ] null null ]");
103   - assert(d->unparse() == "[ null null null null null 5 0 R null [ 0 1 2 3 ] null null ]");
  102 + assert(c->unparse() == "[ null null null null null 3 0 R null [ 0 1 42 3 ] null null ]");
  103 + assert(d->unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]");
104 104  
105 105 try {
106 106 b.setAt(3, {});
... ...
qpdf/qpdf.testcov
... ... @@ -675,7 +675,6 @@ QPDF_json ignore second-level key 0
675 675 QPDF_json ignore unknown key in object_top 0
676 676 QPDF_json ignore unknown key in trailer 0
677 677 QPDF_json ignore unknown key in stream 0
678   -QPDF_json non-trivial null reserved 0
679 678 QPDF_json data and datafile 0
680 679 QPDF_json no stream data in update mode 0
681 680 QPDF_json updating existing stream 0
... ...
qpdf/qtest/qpdf/dangling-bad-xref-dangling-out.pdf
No preview for this file type
qpdf/qtest/qpdf/dangling-bad-xref-dangling.out
1 1 WARNING: dangling-bad-xref.pdf: file is damaged
2 2 WARNING: dangling-bad-xref.pdf (object 7 0, offset 10000): expected n n obj
3 3 WARNING: dangling-bad-xref.pdf: Attempting to reconstruct cross-reference table
4   -new object: 13 0 R
  4 +new object: 12 0 R
5 5 all objects
6 6 1 0 R
7 7 2 0 R
... ... @@ -10,10 +10,6 @@ all objects
10 10 5 0 R
11 11 6 0 R
12 12 7 0 R
13   -8 0 R
14   -9 0 R
15   -10 0 R
16 13 11 0 R
17 14 12 0 R
18   -13 0 R
19 15 test 53 done
... ...
qpdf/qtest/qpdf/dangling-refs-dangling-out.pdf
No preview for this file type
qpdf/qtest/qpdf/dangling-refs-dangling.out
1   -new object: 11 0 R
  1 +new object: 8 0 R
2 2 all objects
3 3 1 0 R
4 4 2 0 R
... ... @@ -8,7 +8,4 @@ all objects
8 8 6 0 R
9 9 7 0 R
10 10 8 0 R
11   -9 0 R
12   -10 0 R
13   -11 0 R
14 11 test 53 done
... ...
qpdf/qtest/qpdf/good13.out
... ... @@ -7,5 +7,5 @@
7 7 /nesting is direct
8 8 /strings is direct
9 9 unparse: 7 0 R
10   -unparseResolved: << /dangling-ref-for-json-test [ 9 0 R ] /hex#20strings [ (Potato) <01020300040560> (AB) ] /indirect 8 0 R /names [ /nesting /hex#20strings /text#2fplain ] /nesting << /a [ 1 2 << /x (y) >> [ (z) ] ] /b << / (legal) /a [ 1 2 ] >> >> /strings [ (one) <24a2> () (\(\)) (\() (\)) (a\f\b\t\r\nb) (") ("") ("\("\)") <410042> (a\nb) (a b) <efbbbfcf80> <efbbbff09fa594> ] >>
  10 +unparseResolved: << /dangling-ref-for-json-test [ null ] /hex#20strings [ (Potato) <01020300040560> (AB) ] /indirect 8 0 R /names [ /nesting /hex#20strings /text#2fplain ] /nesting << /a [ 1 2 << /x (y) >> [ (z) ] ] /b << / (legal) /a [ 1 2 ] >> >> /strings [ (one) <24a2> () (\(\)) (\() (\)) (a\f\b\t\r\nb) (") ("") ("\("\)") <410042> (a\nb) (a b) <efbbbfcf80> <efbbbff09fa594> ] >>
11 11 test 1 done
... ...
qpdf/qtest/qpdf/good13.qdf
... ... @@ -14,14 +14,14 @@ endobj
14 14 2 0 obj
15 15 <<
16 16 /dangling-ref-for-json-test [
17   - 4 0 R
  17 + null
18 18 ]
19 19 /hex#20strings [
20 20 (Potato)
21 21 <01020300040560>
22 22 (AB)
23 23 ]
24   - /indirect 5 0 R
  24 + /indirect 4 0 R
25 25 /names [
26 26 /nesting
27 27 /hex#20strings
... ... @@ -71,27 +71,22 @@ endobj
71 71 <<
72 72 /Count 1
73 73 /Kids [
74   - 6 0 R
  74 + 5 0 R
75 75 ]
76 76 /Type /Pages
77 77 >>
78 78 endobj
79 79  
80   -%% Original object ID: 9 0
81   -4 0 obj
82   -null
83   -endobj
84   -
85 80 %% Original object ID: 8 0
86   -5 0 obj
  81 +4 0 obj
87 82 (hello)
88 83 endobj
89 84  
90 85 %% Page 1
91 86 %% Original object ID: 3 0
92   -6 0 obj
  87 +5 0 obj
93 88 <<
94   - /Contents 7 0 R
  89 + /Contents 6 0 R
95 90 /MediaBox [
96 91 0
97 92 0
... ... @@ -101,9 +96,9 @@ endobj
101 96 /Parent 3 0 R
102 97 /Resources <<
103 98 /Font <<
104   - /F1 9 0 R
  99 + /F1 8 0 R
105 100 >>
106   - /ProcSet 10 0 R
  101 + /ProcSet 9 0 R
107 102 >>
108 103 /Type /Page
109 104 >>
... ... @@ -111,9 +106,9 @@ endobj
111 106  
112 107 %% Contents for page 1
113 108 %% Original object ID: 4 0
114   -7 0 obj
  109 +6 0 obj
115 110 <<
116   - /Length 8 0 R
  111 + /Length 7 0 R
117 112 >>
118 113 stream
119 114 BT
... ... @@ -124,12 +119,12 @@ ET
124 119 endstream
125 120 endobj
126 121  
127   -8 0 obj
  122 +7 0 obj
128 123 44
129 124 endobj
130 125  
131 126 %% Original object ID: 6 0
132   -9 0 obj
  127 +8 0 obj
133 128 <<
134 129 /BaseFont /Helvetica
135 130 /Encoding /WinAnsiEncoding
... ... @@ -140,7 +135,7 @@ endobj
140 135 endobj
141 136  
142 137 %% Original object ID: 5 0
143   -10 0 obj
  138 +9 0 obj
144 139 [
145 140 /PDF
146 141 /Text
... ... @@ -148,24 +143,23 @@ endobj
148 143 endobj
149 144  
150 145 xref
151   -0 11
  146 +0 10
152 147 0000000000 65535 f
153 148 0000000052 00000 n
154 149 0000000133 00000 n
155   -0000000756 00000 n
156   -0000000855 00000 n
157   -0000000903 00000 n
158   -0000000964 00000 n
159   -0000001207 00000 n
160   -0000001306 00000 n
161   -0000001352 00000 n
162   -0000001497 00000 n
  150 +0000000755 00000 n
  151 +0000000854 00000 n
  152 +0000000915 00000 n
  153 +0000001157 00000 n
  154 +0000001256 00000 n
  155 +0000001302 00000 n
  156 +0000001447 00000 n
163 157 trailer <<
164 158 /QTest 2 0 R
165 159 /Root 1 0 R
166   - /Size 11
  160 + /Size 10
167 161 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
168 162 >>
169 163 startxref
170   -1533
  164 +1482
171 165 %%EOF
... ...
qpdf/qtest/qpdf/good21.out
... ... @@ -5,7 +5,7 @@
5 5 item 2 is direct
6 6 item 3 is indirect
7 7 item 4 is direct
8   - item 5 is indirect
  8 + item 5 is direct
9 9 unparse: 9 0 R
10   -unparseResolved: [ /literal null /indirect 8 0 R /undefined 10 0 R ]
  10 +unparseResolved: [ /literal null /indirect 8 0 R /undefined null ]
11 11 test 1 done
... ...
qpdf/qtest/qpdf/good21.qdf
... ... @@ -18,7 +18,7 @@ endobj
18 18 /indirect
19 19 4 0 R
20 20 /undefined
21   - 5 0 R
  21 + null
22 22 ]
23 23 endobj
24 24  
... ... @@ -27,7 +27,7 @@ endobj
27 27 <<
28 28 /Count 1
29 29 /Kids [
30   - 6 0 R
  30 + 5 0 R
31 31 ]
32 32 /Type /Pages
33 33 >>
... ... @@ -38,16 +38,11 @@ endobj
38 38 null
39 39 endobj
40 40  
41   -%% Original object ID: 10 0
42   -5 0 obj
43   -null
44   -endobj
45   -
46 41 %% Page 1
47 42 %% Original object ID: 3 0
48   -6 0 obj
  43 +5 0 obj
49 44 <<
50   - /Contents 7 0 R
  45 + /Contents 6 0 R
51 46 /MediaBox [
52 47 0
53 48 0
... ... @@ -57,9 +52,9 @@ endobj
57 52 /Parent 3 0 R
58 53 /Resources <<
59 54 /Font <<
60   - /F1 9 0 R
  55 + /F1 8 0 R
61 56 >>
62   - /ProcSet 10 0 R
  57 + /ProcSet 9 0 R
63 58 >>
64 59 /Type /Page
65 60 >>
... ... @@ -67,9 +62,9 @@ endobj
67 62  
68 63 %% Contents for page 1
69 64 %% Original object ID: 4 0
70   -7 0 obj
  65 +6 0 obj
71 66 <<
72   - /Length 8 0 R
  67 + /Length 7 0 R
73 68 >>
74 69 stream
75 70 BT
... ... @@ -80,12 +75,12 @@ ET
80 75 endstream
81 76 endobj
82 77  
83   -8 0 obj
  78 +7 0 obj
84 79 44
85 80 endobj
86 81  
87 82 %% Original object ID: 6 0
88   -9 0 obj
  83 +8 0 obj
89 84 <<
90 85 /BaseFont /Helvetica
91 86 /Encoding /WinAnsiEncoding
... ... @@ -96,7 +91,7 @@ endobj
96 91 endobj
97 92  
98 93 %% Original object ID: 7 0
99   -10 0 obj
  94 +9 0 obj
100 95 [
101 96 /PDF
102 97 /Text
... ... @@ -104,24 +99,23 @@ endobj
104 99 endobj
105 100  
106 101 xref
107   -0 11
  102 +0 10
108 103 0000000000 65535 f
109 104 0000000052 00000 n
110 105 0000000133 00000 n
111   -0000000239 00000 n
112   -0000000338 00000 n
113   -0000000387 00000 n
114   -0000000445 00000 n
115   -0000000688 00000 n
116   -0000000787 00000 n
117   -0000000833 00000 n
118   -0000000978 00000 n
  106 +0000000238 00000 n
  107 +0000000337 00000 n
  108 +0000000395 00000 n
  109 +0000000637 00000 n
  110 +0000000736 00000 n
  111 +0000000782 00000 n
  112 +0000000927 00000 n
119 113 trailer <<
120 114 /QTest 2 0 R
121 115 /Root 1 0 R
122   - /Size 11
  116 + /Size 10
123 117 /ID [<06c2c8fc54c5f9cc9246898e1e1a7146><31415926535897932384626433832795>]
124 118 >>
125 119 startxref
126   -1014
  120 +962
127 121 %%EOF
... ...
qpdf/qtest/qpdf/json-changed-good13.pdf
... ... @@ -14,14 +14,14 @@ endobj
14 14 2 0 obj
15 15 <<
16 16 /dangling-ref-for-json-test [
17   - 4 0 R
  17 + null
18 18 ]
19 19 /hex#20strings [
20 20 (Potato)
21 21 <01020300040560>
22 22 (AB)
23 23 ]
24   - /indirect 5 0 R
  24 + /indirect 4 0 R
25 25 /names [
26 26 /nesting
27 27 /hex#20strings
... ... @@ -71,27 +71,22 @@ endobj
71 71 <<
72 72 /Count 1
73 73 /Kids [
74   - 6 0 R
  74 + 5 0 R
75 75 ]
76 76 /Type /Pages
77 77 >>
78 78 endobj
79 79  
80   -%% Original object ID: 9 0
81   -4 0 obj
82   -null
83   -endobj
84   -
85 80 %% Original object ID: 8 0
86   -5 0 obj
  81 +4 0 obj
87 82 (hello)
88 83 endobj
89 84  
90 85 %% Page 1
91 86 %% Original object ID: 3 0
92   -6 0 obj
  87 +5 0 obj
93 88 <<
94   - /Contents 7 0 R
  89 + /Contents 6 0 R
95 90 /MediaBox [
96 91 0
97 92 0
... ... @@ -101,9 +96,9 @@ endobj
101 96 /Parent 3 0 R
102 97 /Resources <<
103 98 /Font <<
104   - /F1 9 0 R
  99 + /F1 8 0 R
105 100 >>
106   - /ProcSet 10 0 R
  101 + /ProcSet 9 0 R
107 102 >>
108 103 /Type /Page
109 104 >>
... ... @@ -111,9 +106,9 @@ endobj
111 106  
112 107 %% Contents for page 1
113 108 %% Original object ID: 4 0
114   -7 0 obj
  109 +6 0 obj
115 110 <<
116   - /Length 8 0 R
  111 + /Length 7 0 R
117 112 >>
118 113 stream
119 114 BT
... ... @@ -124,12 +119,12 @@ ET
124 119 endstream
125 120 endobj
126 121  
127   -8 0 obj
  122 +7 0 obj
128 123 44
129 124 endobj
130 125  
131 126 %% Original object ID: 6 0
132   -9 0 obj
  127 +8 0 obj
133 128 <<
134 129 /BaseFont /Helvetica
135 130 /Encoding /WinAnsiEncoding
... ... @@ -140,7 +135,7 @@ endobj
140 135 endobj
141 136  
142 137 %% Original object ID: 5 0
143   -10 0 obj
  138 +9 0 obj
144 139 [
145 140 /PDF
146 141 /Text
... ... @@ -148,24 +143,23 @@ endobj
148 143 endobj
149 144  
150 145 xref
151   -0 11
  146 +0 10
152 147 0000000000 65535 f
153 148 0000000052 00000 n
154 149 0000000133 00000 n
155   -0000000752 00000 n
156   -0000000851 00000 n
157   -0000000899 00000 n
158   -0000000960 00000 n
159   -0000001203 00000 n
160   -0000001302 00000 n
161   -0000001348 00000 n
162   -0000001493 00000 n
  150 +0000000751 00000 n
  151 +0000000850 00000 n
  152 +0000000911 00000 n
  153 +0000001153 00000 n
  154 +0000001252 00000 n
  155 +0000001298 00000 n
  156 +0000001443 00000 n
163 157 trailer <<
164 158 /QTest 2 0 R
165 159 /Root 1 0 R
166   - /Size 11
  160 + /Size 10
167 161 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
168 162 >>
169 163 startxref
170   -1529
  164 +1478
171 165 %%EOF
... ...
qpdf/qtest/qpdf/replace-with-stream-updated.pdf
... ... @@ -14,14 +14,14 @@ endobj
14 14 2 0 obj
15 15 <<
16 16 /dangling-ref-for-json-test [
17   - 4 0 R
  17 + null
18 18 ]
19 19 /hex#20strings [
20 20 (Potato)
21 21 <01020300040560>
22 22 (AB)
23 23 ]
24   - /indirect 5 0 R
  24 + /indirect 4 0 R
25 25 /names [
26 26 /nesting
27 27 /hex#20strings
... ... @@ -71,37 +71,32 @@ endobj
71 71 <<
72 72 /Count 1
73 73 /Kids [
74   - 7 0 R
  74 + 6 0 R
75 75 ]
76 76 /Type /Pages
77 77 >>
78 78 endobj
79 79  
80   -%% Original object ID: 9 0
81   -4 0 obj
82   -null
83   -endobj
84   -
85 80 %% Original object ID: 8 0
86   -5 0 obj
  81 +4 0 obj
87 82 <<
88 83 /K /V
89   - /Length 6 0 R
  84 + /Length 5 0 R
90 85 >>
91 86 stream
92 87 new-stream-here
93 88 endstream
94 89 endobj
95 90  
96   -6 0 obj
  91 +5 0 obj
97 92 16
98 93 endobj
99 94  
100 95 %% Page 1
101 96 %% Original object ID: 3 0
102   -7 0 obj
  97 +6 0 obj
103 98 <<
104   - /Contents 8 0 R
  99 + /Contents 7 0 R
105 100 /MediaBox [
106 101 0
107 102 0
... ... @@ -111,9 +106,9 @@ endobj
111 106 /Parent 3 0 R
112 107 /Resources <<
113 108 /Font <<
114   - /F1 10 0 R
  109 + /F1 9 0 R
115 110 >>
116   - /ProcSet 11 0 R
  111 + /ProcSet 10 0 R
117 112 >>
118 113 /Type /Page
119 114 >>
... ... @@ -121,9 +116,9 @@ endobj
121 116  
122 117 %% Contents for page 1
123 118 %% Original object ID: 4 0
124   -8 0 obj
  119 +7 0 obj
125 120 <<
126   - /Length 9 0 R
  121 + /Length 8 0 R
127 122 >>
128 123 stream
129 124 BT
... ... @@ -134,12 +129,12 @@ ET
134 129 endstream
135 130 endobj
136 131  
137   -9 0 obj
  132 +8 0 obj
138 133 44
139 134 endobj
140 135  
141 136 %% Original object ID: 6 0
142   -10 0 obj
  137 +9 0 obj
143 138 <<
144 139 /BaseFont /Helvetica
145 140 /Encoding /WinAnsiEncoding
... ... @@ -150,7 +145,7 @@ endobj
150 145 endobj
151 146  
152 147 %% Original object ID: 5 0
153   -11 0 obj
  148 +10 0 obj
154 149 [
155 150 /PDF
156 151 /Text
... ... @@ -158,25 +153,24 @@ endobj
158 153 endobj
159 154  
160 155 xref
161   -0 12
  156 +0 11
162 157 0000000000 65535 f
163 158 0000000052 00000 n
164 159 0000000133 00000 n
165   -0000000756 00000 n
166   -0000000855 00000 n
167   -0000000903 00000 n
168   -0000000982 00000 n
169   -0000001038 00000 n
170   -0000001282 00000 n
171   -0000001381 00000 n
172   -0000001427 00000 n
173   -0000001573 00000 n
  160 +0000000755 00000 n
  161 +0000000854 00000 n
  162 +0000000933 00000 n
  163 +0000000989 00000 n
  164 +0000001232 00000 n
  165 +0000001331 00000 n
  166 +0000001377 00000 n
  167 +0000001522 00000 n
174 168 trailer <<
175 169 /QTest 2 0 R
176 170 /Root 1 0 R
177   - /Size 12
  171 + /Size 11
178 172 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
179 173 >>
180 174 startxref
181   -1609
  175 +1558
182 176 %%EOF
... ...
qpdf/qtest/qpdf/update-stream-data-updated.pdf
... ... @@ -14,14 +14,14 @@ endobj
14 14 2 0 obj
15 15 <<
16 16 /dangling-ref-for-json-test [
17   - 4 0 R
  17 + null
18 18 ]
19 19 /hex#20strings [
20 20 (Potato)
21 21 <01020300040560>
22 22 (AB)
23 23 ]
24   - /indirect 5 0 R
  24 + /indirect 4 0 R
25 25 /names [
26 26 /nesting
27 27 /hex#20strings
... ... @@ -71,27 +71,22 @@ endobj
71 71 <<
72 72 /Count 1
73 73 /Kids [
74   - 6 0 R
  74 + 5 0 R
75 75 ]
76 76 /Type /Pages
77 77 >>
78 78 endobj
79 79  
80   -%% Original object ID: 9 0
81   -4 0 obj
82   -null
83   -endobj
84   -
85 80 %% Original object ID: 8 0
86   -5 0 obj
  81 +4 0 obj
87 82 (hello)
88 83 endobj
89 84  
90 85 %% Page 1
91 86 %% Original object ID: 3 0
92   -6 0 obj
  87 +5 0 obj
93 88 <<
94   - /Contents 7 0 R
  89 + /Contents 6 0 R
95 90 /MediaBox [
96 91 0
97 92 0
... ... @@ -101,9 +96,9 @@ endobj
101 96 /Parent 3 0 R
102 97 /Resources <<
103 98 /Font <<
104   - /F1 9 0 R
  99 + /F1 8 0 R
105 100 >>
106   - /ProcSet 10 0 R
  101 + /ProcSet 9 0 R
107 102 >>
108 103 /Type /Page
109 104 >>
... ... @@ -111,9 +106,9 @@ endobj
111 106  
112 107 %% Contents for page 1
113 108 %% Original object ID: 4 0
114   -7 0 obj
  109 +6 0 obj
115 110 <<
116   - /Length 8 0 R
  111 + /Length 7 0 R
117 112 >>
118 113 stream
119 114 BT
... ... @@ -124,12 +119,12 @@ ET
124 119 endstream
125 120 endobj
126 121  
127   -8 0 obj
  122 +7 0 obj
128 123 43
129 124 endobj
130 125  
131 126 %% Original object ID: 6 0
132   -9 0 obj
  127 +8 0 obj
133 128 <<
134 129 /BaseFont /Helvetica
135 130 /Encoding /WinAnsiEncoding
... ... @@ -140,7 +135,7 @@ endobj
140 135 endobj
141 136  
142 137 %% Original object ID: 5 0
143   -10 0 obj
  138 +9 0 obj
144 139 [
145 140 /PDF
146 141 /Text
... ... @@ -148,24 +143,23 @@ endobj
148 143 endobj
149 144  
150 145 xref
151   -0 11
  146 +0 10
152 147 0000000000 65535 f
153 148 0000000052 00000 n
154 149 0000000133 00000 n
155   -0000000756 00000 n
156   -0000000855 00000 n
157   -0000000903 00000 n
158   -0000000964 00000 n
159   -0000001207 00000 n
160   -0000001305 00000 n
161   -0000001351 00000 n
162   -0000001496 00000 n
  150 +0000000755 00000 n
  151 +0000000854 00000 n
  152 +0000000915 00000 n
  153 +0000001157 00000 n
  154 +0000001255 00000 n
  155 +0000001301 00000 n
  156 +0000001446 00000 n
163 157 trailer <<
164 158 /QTest 2 0 R
165 159 /Root 1 0 R
166   - /Size 11
  160 + /Size 10
167 161 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
168 162 >>
169 163 startxref
170   -1532
  164 +1481
171 165 %%EOF
... ...
qpdf/qtest/qpdf/update-stream-dict-only-updated.pdf
... ... @@ -14,14 +14,14 @@ endobj
14 14 2 0 obj
15 15 <<
16 16 /dangling-ref-for-json-test [
17   - 4 0 R
  17 + null
18 18 ]
19 19 /hex#20strings [
20 20 (Potato)
21 21 <01020300040560>
22 22 (AB)
23 23 ]
24   - /indirect 5 0 R
  24 + /indirect 4 0 R
25 25 /names [
26 26 /nesting
27 27 /hex#20strings
... ... @@ -71,27 +71,22 @@ endobj
71 71 <<
72 72 /Count 1
73 73 /Kids [
74   - 6 0 R
  74 + 5 0 R
75 75 ]
76 76 /Type /Pages
77 77 >>
78 78 endobj
79 79  
80   -%% Original object ID: 9 0
81   -4 0 obj
82   -null
83   -endobj
84   -
85 80 %% Original object ID: 8 0
86   -5 0 obj
  81 +4 0 obj
87 82 (hello)
88 83 endobj
89 84  
90 85 %% Page 1
91 86 %% Original object ID: 3 0
92   -6 0 obj
  87 +5 0 obj
93 88 <<
94   - /Contents 7 0 R
  89 + /Contents 6 0 R
95 90 /MediaBox [
96 91 0
97 92 0
... ... @@ -101,9 +96,9 @@ endobj
101 96 /Parent 3 0 R
102 97 /Resources <<
103 98 /Font <<
104   - /F1 9 0 R
  99 + /F1 8 0 R
105 100 >>
106   - /ProcSet 10 0 R
  101 + /ProcSet 9 0 R
107 102 >>
108 103 /Type /Page
109 104 >>
... ... @@ -111,10 +106,10 @@ endobj
111 106  
112 107 %% Contents for page 1
113 108 %% Original object ID: 4 0
114   -7 0 obj
  109 +6 0 obj
115 110 <<
116 111 /Potato (salad)
117   - /Length 8 0 R
  112 + /Length 7 0 R
118 113 >>
119 114 stream
120 115 BT
... ... @@ -125,12 +120,12 @@ ET
125 120 endstream
126 121 endobj
127 122  
128   -8 0 obj
  123 +7 0 obj
129 124 44
130 125 endobj
131 126  
132 127 %% Original object ID: 6 0
133   -9 0 obj
  128 +8 0 obj
134 129 <<
135 130 /BaseFont /Helvetica
136 131 /Encoding /WinAnsiEncoding
... ... @@ -141,7 +136,7 @@ endobj
141 136 endobj
142 137  
143 138 %% Original object ID: 5 0
144   -10 0 obj
  139 +9 0 obj
145 140 [
146 141 /PDF
147 142 /Text
... ... @@ -149,24 +144,23 @@ endobj
149 144 endobj
150 145  
151 146 xref
152   -0 11
  147 +0 10
153 148 0000000000 65535 f
154 149 0000000052 00000 n
155 150 0000000133 00000 n
156   -0000000756 00000 n
157   -0000000855 00000 n
158   -0000000903 00000 n
159   -0000000964 00000 n
160   -0000001207 00000 n
161   -0000001324 00000 n
162   -0000001370 00000 n
163   -0000001515 00000 n
  151 +0000000755 00000 n
  152 +0000000854 00000 n
  153 +0000000915 00000 n
  154 +0000001157 00000 n
  155 +0000001274 00000 n
  156 +0000001320 00000 n
  157 +0000001465 00000 n
164 158 trailer <<
165 159 /QTest 2 0 R
166 160 /Root 1 0 R
167   - /Size 11
  161 + /Size 10
168 162 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
169 163 >>
170 164 startxref
171   -1551
  165 +1500
172 166 %%EOF
... ...