Commit 6aa6c013034c012f7c843427ddf407925fbbf1c3

Authored by m-holger
Committed by GitHub
2 parents 77d1a0cf 08eb6844

Merge pull request #1171 from m-holger/unresolved

Refactor the creation of unresolved objects
fuzz/CMakeLists.txt
@@ -133,6 +133,8 @@ set(CORPUS_OTHER @@ -133,6 +133,8 @@ set(CORPUS_OTHER
133 70055.fuzz 133 70055.fuzz
134 70245.fuzz 134 70245.fuzz
135 70306.fuzz 135 70306.fuzz
  136 + 70306a.fuzz
  137 + 70306b.fuzz
136 ) 138 )
137 139
138 set(CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/qpdf_corpus) 140 set(CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/qpdf_corpus)
fuzz/qpdf_extra/70306a.fuzz 0 → 100644
No preview for this file type
fuzz/qpdf_extra/70306b.fuzz 0 → 100644
No preview for this file type
fuzz/qtest/fuzz.test
@@ -21,7 +21,7 @@ my @fuzzers = ( @@ -21,7 +21,7 @@ my @fuzzers = (
21 ['pngpredictor' => 1], 21 ['pngpredictor' => 1],
22 ['runlength' => 6], 22 ['runlength' => 6],
23 ['tiffpredictor' => 2], 23 ['tiffpredictor' => 2],
24 - ['qpdf' => 75], # increment when adding new files 24 + ['qpdf' => 77], # increment when adding new files
25 ); 25 );
26 26
27 my $n_tests = 0; 27 my $n_tests = 0;
include/qpdf/QPDF.hh
@@ -819,7 +819,8 @@ class QPDF @@ -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 class ParseGuard 824 class ParseGuard
824 { 825 {
825 friend class QPDFParser; 826 friend class QPDFParser;
@@ -832,6 +833,13 @@ class QPDF @@ -832,6 +833,13 @@ class QPDF
832 qpdf->inParse(true); 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 ~ParseGuard() 843 ~ParseGuard()
836 { 844 {
837 if (qpdf) { 845 if (qpdf) {
@@ -900,8 +908,8 @@ class QPDF @@ -900,8 +908,8 @@ class QPDF
900 } 908 }
901 ObjCache( 909 ObjCache(
902 std::shared_ptr<QPDFObject> object, 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 object(object), 913 object(object),
906 end_before_space(end_before_space), 914 end_before_space(end_before_space),
907 end_after_space(end_after_space) 915 end_after_space(end_after_space)
@@ -1065,13 +1073,14 @@ class QPDF @@ -1065,13 +1073,14 @@ class QPDF
1065 QPDFObject* resolve(QPDFObjGen og); 1073 QPDFObject* resolve(QPDFObjGen og);
1066 void resolveObjectsInStream(int obj_stream_number); 1074 void resolveObjectsInStream(int obj_stream_number);
1067 void stopOnError(std::string const& message); 1075 void stopOnError(std::string const& message);
1068 - QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);  
1069 QPDFObjectHandle reserveStream(QPDFObjGen const& og); 1076 QPDFObjectHandle reserveStream(QPDFObjGen const& og);
1070 QPDFObjGen nextObjGen(); 1077 QPDFObjGen nextObjGen();
1071 QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&); 1078 QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr<QPDFObject> const&);
1072 QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj); 1079 QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr<QPDFObject> const& obj);
1073 bool isCached(QPDFObjGen const& og); 1080 bool isCached(QPDFObjGen const& og);
1074 bool isUnresolved(QPDFObjGen const& og); 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 void removeObject(QPDFObjGen og); 1084 void removeObject(QPDFObjGen og);
1076 void updateCache( 1085 void updateCache(
1077 QPDFObjGen const& og, 1086 QPDFObjGen const& og,
libqpdf/QPDF.cc
@@ -654,9 +654,11 @@ QPDF::reconstruct_xref(QPDFExc&amp; e) @@ -654,9 +654,11 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
654 } 654 }
655 check_warnings(); 655 check_warnings();
656 if (!m->parsed) { 656 if (!m->parsed) {
  657 + m->parsed = true;
657 getAllPages(); 658 getAllPages();
658 check_warnings(); 659 check_warnings();
659 if (m->all_pages.empty()) { 660 if (m->all_pages.empty()) {
  661 + m->parsed = false;
660 throw damagedPDF("", 0, "unable to find any pages while recovering damaged file"); 662 throw damagedPDF("", 0, "unable to find any pages while recovering damaged file");
661 } 663 }
662 } 664 }
@@ -1462,7 +1464,8 @@ QPDF::readTrailer() @@ -1462,7 +1464,8 @@ QPDF::readTrailer()
1462 { 1464 {
1463 qpdf_offset_t offset = m->file->tell(); 1465 qpdf_offset_t offset = m->file->tell();
1464 bool empty = false; 1466 bool empty = false;
1465 - auto object = QPDFParser(m->file, "trailer", m->tokenizer, nullptr, this).parse(empty, false); 1467 + auto object =
  1468 + QPDFParser(m->file, "trailer", m->tokenizer, nullptr, this, true).parse(empty, false);
1466 if (empty) { 1469 if (empty) {
1467 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in 1470 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
1468 // actual PDF files and Adobe Reader appears to ignore them. 1471 // actual PDF files and Adobe Reader appears to ignore them.
@@ -1484,8 +1487,9 @@ QPDF::readObject(std::string const&amp; description, QPDFObjGen og) @@ -1484,8 +1487,9 @@ QPDF::readObject(std::string const&amp; description, QPDFObjGen og)
1484 1487
1485 StringDecrypter decrypter{this, og}; 1488 StringDecrypter decrypter{this, og};
1486 StringDecrypter* decrypter_ptr = m->encp->encrypted ? &decrypter : nullptr; 1489 StringDecrypter* decrypter_ptr = m->encp->encrypted ? &decrypter : nullptr;
1487 - auto object = QPDFParser(m->file, m->last_object_description, m->tokenizer, decrypter_ptr, this)  
1488 - .parse(empty, false); 1490 + auto object =
  1491 + QPDFParser(m->file, m->last_object_description, m->tokenizer, decrypter_ptr, this, true)
  1492 + .parse(empty, false);
1489 if (empty) { 1493 if (empty) {
1490 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in 1494 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
1491 // actual PDF files and Adobe Reader appears to ignore them. 1495 // actual PDF files and Adobe Reader appears to ignore them.
@@ -1604,7 +1608,7 @@ QPDF::readObjectInStream(std::shared_ptr&lt;InputSource&gt;&amp; input, int obj) @@ -1604,7 +1608,7 @@ QPDF::readObjectInStream(std::shared_ptr&lt;InputSource&gt;&amp; input, int obj)
1604 m->last_object_description += " 0"; 1608 m->last_object_description += " 0";
1605 1609
1606 bool empty = false; 1610 bool empty = false;
1607 - auto object = QPDFParser(input, m->last_object_description, m->tokenizer, nullptr, this) 1611 + auto object = QPDFParser(input, m->last_object_description, m->tokenizer, nullptr, this, true)
1608 .parse(empty, false); 1612 .parse(empty, false);
1609 if (empty) { 1613 if (empty) {
1610 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in 1614 // Nothing in the PDF spec appears to allow empty objects, but they have been encountered in
@@ -2094,30 +2098,52 @@ QPDF::newStream(std::string const&amp; data) @@ -2094,30 +2098,52 @@ QPDF::newStream(std::string const&amp; data)
2094 } 2098 }
2095 2099
2096 QPDFObjectHandle 2100 QPDFObjectHandle
2097 -QPDF::reserveObjectIfNotExists(QPDFObjGen const& og) 2101 +QPDF::reserveStream(QPDFObjGen const& og)
2098 { 2102 {
2099 - if (!isCached(og) && m->xref_table.count(og) == 0) {  
2100 - updateCache(og, QPDF_Reserved::create(), -1, -1);  
2101 - return newIndirect(og, m->obj_cache[og].object);  
2102 - } else {  
2103 - 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;
2104 } 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;
  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;
2105 } 2121 }
2106 2122
2107 -QPDFObjectHandle  
2108 -QPDF::reserveStream(QPDFObjGen const& og) 2123 +std::shared_ptr<QPDFObject>
  2124 +QPDF::getObjectForJSON(int id, int gen)
2109 { 2125 {
2110 - 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;
2111 } 2134 }
2112 2135
2113 QPDFObjectHandle 2136 QPDFObjectHandle
2114 QPDF::getObject(QPDFObjGen const& og) 2137 QPDF::getObject(QPDFObjGen const& og)
2115 { 2138 {
2116 - // This method is called by the parser and therefore must not resolve any objects.  
2117 - if (!isCached(og)) {  
2118 - 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};
2119 } 2146 }
2120 - return newIndirect(og, m->obj_cache[og].object);  
2121 } 2147 }
2122 2148
2123 QPDFObjectHandle 2149 QPDFObjectHandle
libqpdf/QPDFObjectHandle.cc
@@ -2146,7 +2146,8 @@ QPDFObjectHandle::parseContentStream_data( @@ -2146,7 +2146,8 @@ QPDFObjectHandle::parseContentStream_data(
2146 tokenizer.readToken(input, "content", true); 2146 tokenizer.readToken(input, "content", true);
2147 qpdf_offset_t offset = input->getLastOffset(); 2147 qpdf_offset_t offset = input->getLastOffset();
2148 input->seek(offset, SEEK_SET); 2148 input->seek(offset, SEEK_SET);
2149 - auto obj = QPDFParser(input, "content", tokenizer, nullptr, context).parse(empty, true); 2149 + auto obj =
  2150 + QPDFParser(input, "content", tokenizer, nullptr, context, false).parse(empty, true);
2150 if (!obj.isInitialized()) { 2151 if (!obj.isInitialized()) {
2151 // EOF 2152 // EOF
2152 break; 2153 break;
@@ -2205,7 +2206,8 @@ QPDFObjectHandle::parse( @@ -2205,7 +2206,8 @@ QPDFObjectHandle::parse(
2205 StringDecrypter* decrypter, 2206 StringDecrypter* decrypter,
2206 QPDF* context) 2207 QPDF* context)
2207 { 2208 {
2208 - return QPDFParser(input, object_description, tokenizer, decrypter, context).parse(empty, false); 2209 + return QPDFParser(input, object_description, tokenizer, decrypter, context, false)
  2210 + .parse(empty, false);
2209 } 2211 }
2210 2212
2211 #ifndef QPDF_FUTURE 2213 #ifndef QPDF_FUTURE
libqpdf/QPDFOutlineDocumentHelper.cc
@@ -71,7 +71,7 @@ QPDFOutlineDocumentHelper::resolveNamedDest(QPDFObjectHandle name) @@ -71,7 +71,7 @@ QPDFOutlineDocumentHelper::resolveNamedDest(QPDFObjectHandle name)
71 m->dest_dict = qpdf.getRoot().getKey("/Dests"); 71 m->dest_dict = qpdf.getRoot().getKey("/Dests");
72 } 72 }
73 QTC::TC("qpdf", "QPDFOutlineDocumentHelper name named dest"); 73 QTC::TC("qpdf", "QPDFOutlineDocumentHelper name named dest");
74 - result= m->dest_dict.getKeyIfDict(name.getName()); 74 + result = m->dest_dict.getKeyIfDict(name.getName());
75 } else if (name.isString()) { 75 } else if (name.isString()) {
76 if (!m->names_dest) { 76 if (!m->names_dest) {
77 auto dests = qpdf.getRoot().getKey("/Names").getKeyIfDict("/Dests"); 77 auto dests = qpdf.getRoot().getKey("/Names").getKeyIfDict("/Dests");
libqpdf/QPDFParser.cc
@@ -166,10 +166,7 @@ QPDFParser::parseRemainder(bool content_stream) @@ -166,10 +166,7 @@ QPDFParser::parseRemainder(bool content_stream)
166 auto id = QIntC::to_int(int_buffer[(int_count - 1) % 2]); 166 auto id = QIntC::to_int(int_buffer[(int_count - 1) % 2]);
167 auto gen = QIntC::to_int(int_buffer[(int_count) % 2]); 167 auto gen = QIntC::to_int(int_buffer[(int_count) % 2]);
168 if (!(id < 1 || gen < 0 || gen >= 65535)) { 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 } else { 170 } else {
174 QTC::TC("qpdf", "QPDFParser invalid objgen"); 171 QTC::TC("qpdf", "QPDFParser invalid objgen");
175 addNull(); 172 addNull();
libqpdf/QPDFWriter.cc
@@ -1237,7 +1237,7 @@ bool @@ -1237,7 +1237,7 @@ bool
1237 QPDFWriter::willFilterStream( 1237 QPDFWriter::willFilterStream(
1238 QPDFObjectHandle stream, 1238 QPDFObjectHandle stream,
1239 bool& compress_stream, // out only 1239 bool& compress_stream, // out only
1240 - bool& is_metadata, // out only 1240 + bool& is_metadata, // out only
1241 std::shared_ptr<Buffer>* stream_data) 1241 std::shared_ptr<Buffer>* stream_data)
1242 { 1242 {
1243 compress_stream = false; 1243 compress_stream = false;
libqpdf/QPDF_Null.cc
@@ -3,15 +3,15 @@ @@ -3,15 +3,15 @@
3 #include <qpdf/JSON_writer.hh> 3 #include <qpdf/JSON_writer.hh>
4 #include <qpdf/QPDFObject_private.hh> 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 std::shared_ptr<QPDFObject> 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 std::shared_ptr<QPDFObject> 17 std::shared_ptr<QPDFObject>
libqpdf/QPDF_json.cc
@@ -240,11 +240,6 @@ class QPDF::JSONReactor: public JSON::Reactor @@ -240,11 +240,6 @@ class QPDF::JSONReactor: public JSON::Reactor
240 descr(std::make_shared<QPDFValue::Description>( 240 descr(std::make_shared<QPDFValue::Description>(
241 QPDFValue::JSON_Descr(std::make_shared<std::string>(is->getName()), ""))) 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 ~JSONReactor() override = default; 244 ~JSONReactor() override = default;
250 void dictionaryStart() override; 245 void dictionaryStart() override;
@@ -272,10 +267,10 @@ class QPDF::JSONReactor: public JSON::Reactor @@ -272,10 +267,10 @@ class QPDF::JSONReactor: public JSON::Reactor
272 struct StackFrame 267 struct StackFrame
273 { 268 {
274 StackFrame(state_e state) : 269 StackFrame(state_e state) :
275 - state(state){}; 270 + state(state) {};
276 StackFrame(state_e state, QPDFObjectHandle&& object) : 271 StackFrame(state_e state, QPDFObjectHandle&& object) :
277 state(state), 272 state(state),
278 - object(object){}; 273 + object(object) {};
279 state_e state; 274 state_e state;
280 QPDFObjectHandle object; 275 QPDFObjectHandle object;
281 }; 276 };
@@ -305,7 +300,6 @@ class QPDF::JSONReactor: public JSON::Reactor @@ -305,7 +300,6 @@ class QPDF::JSONReactor: public JSON::Reactor
305 bool saw_data{false}; 300 bool saw_data{false};
306 bool saw_datafile{false}; 301 bool saw_datafile{false};
307 bool this_stream_needs_data{false}; 302 bool this_stream_needs_data{false};
308 - std::set<QPDFObjGen> reserved;  
309 std::vector<StackFrame> stack; 303 std::vector<StackFrame> stack;
310 QPDFObjectHandle next_obj; 304 QPDFObjectHandle next_obj;
311 state_e next_state{st_top}; 305 state_e next_state{st_top};
@@ -416,16 +410,6 @@ QPDF::JSONReactor::containerEnd(JSON const&amp; value) @@ -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 if (!stack.empty()) { 414 if (!stack.empty()) {
431 auto state = stack.back().state; 415 auto state = stack.back().state;
@@ -565,7 +549,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value) @@ -565,7 +549,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const&amp; key, JSON const&amp; value)
565 } else if (is_obj_key(key, obj, gen)) { 549 } else if (is_obj_key(key, obj, gen)) {
566 this->cur_object = key; 550 this->cur_object = key;
567 if (setNextStateIfDictionary(key, value, st_object_top)) { 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 } else { 554 } else {
571 QTC::TC("qpdf", "QPDF_json bad object key"); 555 QTC::TC("qpdf", "QPDF_json bad object key");
@@ -767,7 +751,7 @@ QPDF::JSONReactor::makeObject(JSON const&amp; value) @@ -767,7 +751,7 @@ QPDF::JSONReactor::makeObject(JSON const&amp; value)
767 int gen = 0; 751 int gen = 0;
768 std::string str; 752 std::string str;
769 if (is_indirect_object(str_v, obj, gen)) { 753 if (is_indirect_object(str_v, obj, gen)) {
770 - result = pdf.reserveObjectIfNotExists(QPDFObjGen(obj, gen)); 754 + result = pdf.getObjectForJSON(obj, gen);
771 } else if (is_unicode_string(str_v, str)) { 755 } else if (is_unicode_string(str_v, str)) {
772 result = QPDFObjectHandle::newUnicodeString(str); 756 result = QPDFObjectHandle::newUnicodeString(str);
773 } else if (is_binary_string(str_v, str)) { 757 } else if (is_binary_string(str_v, str)) {
libqpdf/qpdf/QPDFParser.hh
@@ -16,14 +16,16 @@ class QPDFParser @@ -16,14 +16,16 @@ class QPDFParser
16 std::string const& object_description, 16 std::string const& object_description,
17 QPDFTokenizer& tokenizer, 17 QPDFTokenizer& tokenizer,
18 QPDFObjectHandle::StringDecrypter* decrypter, 18 QPDFObjectHandle::StringDecrypter* decrypter,
19 - QPDF* context) : 19 + QPDF* context,
  20 + bool parse_pdf) :
20 input(input), 21 input(input),
21 object_description(object_description), 22 object_description(object_description),
22 tokenizer(tokenizer), 23 tokenizer(tokenizer),
23 decrypter(decrypter), 24 decrypter(decrypter),
24 context(context), 25 context(context),
25 description(std::make_shared<QPDFValue::Description>( 26 description(std::make_shared<QPDFValue::Description>(
26 - std::string(input->getName() + ", " + object_description + " at offset $PO"))) 27 + std::string(input->getName() + ", " + object_description + " at offset $PO"))),
  28 + parse_pdf(parse_pdf)
27 { 29 {
28 } 30 }
29 virtual ~QPDFParser() = default; 31 virtual ~QPDFParser() = default;
@@ -76,6 +78,8 @@ class QPDFParser @@ -76,6 +78,8 @@ class QPDFParser
76 QPDFObjectHandle::StringDecrypter* decrypter; 78 QPDFObjectHandle::StringDecrypter* decrypter;
77 QPDF* context; 79 QPDF* context;
78 std::shared_ptr<QPDFValue::Description> description; 80 std::shared_ptr<QPDFValue::Description> description;
  81 + bool parse_pdf;
  82 +
79 std::vector<StackFrame> stack; 83 std::vector<StackFrame> stack;
80 StackFrame* frame; 84 StackFrame* frame;
81 // Number of recent bad tokens. 85 // Number of recent bad tokens.
libqpdf/qpdf/QPDF_Null.hh
@@ -7,7 +7,7 @@ class QPDF_Null: public QPDFValue @@ -7,7 +7,7 @@ class QPDF_Null: public QPDFValue
7 { 7 {
8 public: 8 public:
9 ~QPDF_Null() override = default; 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 static std::shared_ptr<QPDFObject> create( 11 static std::shared_ptr<QPDFObject> create(
12 std::shared_ptr<QPDFObject> parent, 12 std::shared_ptr<QPDFObject> parent,
13 std::string_view const& static_descr, 13 std::string_view const& static_descr,
@@ -21,7 +21,7 @@ class QPDF_Null: public QPDFValue @@ -21,7 +21,7 @@ class QPDF_Null: public QPDFValue
21 void writeJSON(int json_version, JSON::Writer& p) override; 21 void writeJSON(int json_version, JSON::Writer& p) override;
22 22
23 private: 23 private:
24 - QPDF_Null(); 24 + QPDF_Null(QPDF* qpdf = nullptr, QPDFObjGen og = QPDFObjGen());
25 }; 25 };
26 26
27 #endif // QPDF_NULL_HH 27 #endif // QPDF_NULL_HH
libqpdf/qpdf/qpdf-c_impl.hh
@@ -16,7 +16,7 @@ struct _qpdf_data @@ -16,7 +16,7 @@ struct _qpdf_data
16 _qpdf_data() = default; 16 _qpdf_data() = default;
17 17
18 _qpdf_data(std::unique_ptr<QPDF>&& qpdf) : 18 _qpdf_data(std::unique_ptr<QPDF>&& qpdf) :
19 - qpdf(std::move(qpdf)){}; 19 + qpdf(std::move(qpdf)) {};
20 20
21 ~_qpdf_data() = default; 21 ~_qpdf_data() = default;
22 22
libtests/sparse_array.cc
@@ -90,17 +90,17 @@ main() @@ -90,17 +90,17 @@ main()
90 90
91 obj = QPDF_Array::create({10, "null"_qpdf.getObj()}, true); 91 obj = QPDF_Array::create({10, "null"_qpdf.getObj()}, true);
92 QPDF_Array& b = *obj->as<QPDF_Array>(); 92 QPDF_Array& b = *obj->as<QPDF_Array>();
93 - b.setAt(5, pdf.getObject(5, 0)); 93 + b.setAt(5, pdf.newIndirectNull());
94 b.setAt(7, "[0 1 2 3]"_qpdf); 94 b.setAt(7, "[0 1 2 3]"_qpdf);
95 assert(b.at(3).isNull()); 95 assert(b.at(3).isNull());
96 assert(b.at(8).isNull()); 96 assert(b.at(8).isNull());
97 assert(b.at(5).isIndirect()); 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 auto c = b.copy(true); 99 auto c = b.copy(true);
100 auto d = b.copy(false); 100 auto d = b.copy(false);
101 b.at(7).setArrayItem(2, "42"_qpdf); 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 try { 105 try {
106 b.setAt(3, {}); 106 b.setAt(3, {});
qpdf/qpdf.testcov
@@ -675,7 +675,6 @@ QPDF_json ignore second-level key 0 @@ -675,7 +675,6 @@ QPDF_json ignore second-level key 0
675 QPDF_json ignore unknown key in object_top 0 675 QPDF_json ignore unknown key in object_top 0
676 QPDF_json ignore unknown key in trailer 0 676 QPDF_json ignore unknown key in trailer 0
677 QPDF_json ignore unknown key in stream 0 677 QPDF_json ignore unknown key in stream 0
678 -QPDF_json non-trivial null reserved 0  
679 QPDF_json data and datafile 0 678 QPDF_json data and datafile 0
680 QPDF_json no stream data in update mode 0 679 QPDF_json no stream data in update mode 0
681 QPDF_json updating existing stream 0 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 WARNING: dangling-bad-xref.pdf: file is damaged 1 WARNING: dangling-bad-xref.pdf: file is damaged
2 WARNING: dangling-bad-xref.pdf (object 7 0, offset 10000): expected n n obj 2 WARNING: dangling-bad-xref.pdf (object 7 0, offset 10000): expected n n obj
3 WARNING: dangling-bad-xref.pdf: Attempting to reconstruct cross-reference table 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 all objects 5 all objects
6 1 0 R 6 1 0 R
7 2 0 R 7 2 0 R
@@ -10,10 +10,6 @@ all objects @@ -10,10 +10,6 @@ all objects
10 5 0 R 10 5 0 R
11 6 0 R 11 6 0 R
12 7 0 R 12 7 0 R
13 -8 0 R  
14 -9 0 R  
15 -10 0 R  
16 11 0 R 13 11 0 R
17 12 0 R 14 12 0 R
18 -13 0 R  
19 test 53 done 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 all objects 2 all objects
3 1 0 R 3 1 0 R
4 2 0 R 4 2 0 R
@@ -8,7 +8,4 @@ all objects @@ -8,7 +8,4 @@ all objects
8 6 0 R 8 6 0 R
9 7 0 R 9 7 0 R
10 8 0 R 10 8 0 R
11 -9 0 R  
12 -10 0 R  
13 -11 0 R  
14 test 53 done 11 test 53 done
qpdf/qtest/qpdf/good13.out
@@ -7,5 +7,5 @@ @@ -7,5 +7,5 @@
7 /nesting is direct 7 /nesting is direct
8 /strings is direct 8 /strings is direct
9 unparse: 7 0 R 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 test 1 done 11 test 1 done
qpdf/qtest/qpdf/good13.qdf
@@ -14,14 +14,14 @@ endobj @@ -14,14 +14,14 @@ endobj
14 2 0 obj 14 2 0 obj
15 << 15 <<
16 /dangling-ref-for-json-test [ 16 /dangling-ref-for-json-test [
17 - 4 0 R 17 + null
18 ] 18 ]
19 /hex#20strings [ 19 /hex#20strings [
20 (Potato) 20 (Potato)
21 <01020300040560> 21 <01020300040560>
22 (AB) 22 (AB)
23 ] 23 ]
24 - /indirect 5 0 R 24 + /indirect 4 0 R
25 /names [ 25 /names [
26 /nesting 26 /nesting
27 /hex#20strings 27 /hex#20strings
@@ -71,27 +71,22 @@ endobj @@ -71,27 +71,22 @@ endobj
71 << 71 <<
72 /Count 1 72 /Count 1
73 /Kids [ 73 /Kids [
74 - 6 0 R 74 + 5 0 R
75 ] 75 ]
76 /Type /Pages 76 /Type /Pages
77 >> 77 >>
78 endobj 78 endobj
79 79
80 -%% Original object ID: 9 0  
81 -4 0 obj  
82 -null  
83 -endobj  
84 -  
85 %% Original object ID: 8 0 80 %% Original object ID: 8 0
86 -5 0 obj 81 +4 0 obj
87 (hello) 82 (hello)
88 endobj 83 endobj
89 84
90 %% Page 1 85 %% Page 1
91 %% Original object ID: 3 0 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 /MediaBox [ 90 /MediaBox [
96 0 91 0
97 0 92 0
@@ -101,9 +96,9 @@ endobj @@ -101,9 +96,9 @@ endobj
101 /Parent 3 0 R 96 /Parent 3 0 R
102 /Resources << 97 /Resources <<
103 /Font << 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 /Type /Page 103 /Type /Page
109 >> 104 >>
@@ -111,9 +106,9 @@ endobj @@ -111,9 +106,9 @@ endobj
111 106
112 %% Contents for page 1 107 %% Contents for page 1
113 %% Original object ID: 4 0 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 stream 113 stream
119 BT 114 BT
@@ -124,12 +119,12 @@ ET @@ -124,12 +119,12 @@ ET
124 endstream 119 endstream
125 endobj 120 endobj
126 121
127 -8 0 obj 122 +7 0 obj
128 44 123 44
129 endobj 124 endobj
130 125
131 %% Original object ID: 6 0 126 %% Original object ID: 6 0
132 -9 0 obj 127 +8 0 obj
133 << 128 <<
134 /BaseFont /Helvetica 129 /BaseFont /Helvetica
135 /Encoding /WinAnsiEncoding 130 /Encoding /WinAnsiEncoding
@@ -140,7 +135,7 @@ endobj @@ -140,7 +135,7 @@ endobj
140 endobj 135 endobj
141 136
142 %% Original object ID: 5 0 137 %% Original object ID: 5 0
143 -10 0 obj 138 +9 0 obj
144 [ 139 [
145 /PDF 140 /PDF
146 /Text 141 /Text
@@ -148,24 +143,23 @@ endobj @@ -148,24 +143,23 @@ endobj
148 endobj 143 endobj
149 144
150 xref 145 xref
151 -0 11 146 +0 10
152 0000000000 65535 f 147 0000000000 65535 f
153 0000000052 00000 n 148 0000000052 00000 n
154 0000000133 00000 n 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 trailer << 157 trailer <<
164 /QTest 2 0 R 158 /QTest 2 0 R
165 /Root 1 0 R 159 /Root 1 0 R
166 - /Size 11 160 + /Size 10
167 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] 161 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
168 >> 162 >>
169 startxref 163 startxref
170 -1533 164 +1482
171 %%EOF 165 %%EOF
qpdf/qtest/qpdf/good21.out
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 item 2 is direct 5 item 2 is direct
6 item 3 is indirect 6 item 3 is indirect
7 item 4 is direct 7 item 4 is direct
8 - item 5 is indirect 8 + item 5 is direct
9 unparse: 9 0 R 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 test 1 done 11 test 1 done
qpdf/qtest/qpdf/good21.qdf
@@ -18,7 +18,7 @@ endobj @@ -18,7 +18,7 @@ endobj
18 /indirect 18 /indirect
19 4 0 R 19 4 0 R
20 /undefined 20 /undefined
21 - 5 0 R 21 + null
22 ] 22 ]
23 endobj 23 endobj
24 24
@@ -27,7 +27,7 @@ endobj @@ -27,7 +27,7 @@ endobj
27 << 27 <<
28 /Count 1 28 /Count 1
29 /Kids [ 29 /Kids [
30 - 6 0 R 30 + 5 0 R
31 ] 31 ]
32 /Type /Pages 32 /Type /Pages
33 >> 33 >>
@@ -38,16 +38,11 @@ endobj @@ -38,16 +38,11 @@ endobj
38 null 38 null
39 endobj 39 endobj
40 40
41 -%% Original object ID: 10 0  
42 -5 0 obj  
43 -null  
44 -endobj  
45 -  
46 %% Page 1 41 %% Page 1
47 %% Original object ID: 3 0 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 /MediaBox [ 46 /MediaBox [
52 0 47 0
53 0 48 0
@@ -57,9 +52,9 @@ endobj @@ -57,9 +52,9 @@ endobj
57 /Parent 3 0 R 52 /Parent 3 0 R
58 /Resources << 53 /Resources <<
59 /Font << 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 /Type /Page 59 /Type /Page
65 >> 60 >>
@@ -67,9 +62,9 @@ endobj @@ -67,9 +62,9 @@ endobj
67 62
68 %% Contents for page 1 63 %% Contents for page 1
69 %% Original object ID: 4 0 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 stream 69 stream
75 BT 70 BT
@@ -80,12 +75,12 @@ ET @@ -80,12 +75,12 @@ ET
80 endstream 75 endstream
81 endobj 76 endobj
82 77
83 -8 0 obj 78 +7 0 obj
84 44 79 44
85 endobj 80 endobj
86 81
87 %% Original object ID: 6 0 82 %% Original object ID: 6 0
88 -9 0 obj 83 +8 0 obj
89 << 84 <<
90 /BaseFont /Helvetica 85 /BaseFont /Helvetica
91 /Encoding /WinAnsiEncoding 86 /Encoding /WinAnsiEncoding
@@ -96,7 +91,7 @@ endobj @@ -96,7 +91,7 @@ endobj
96 endobj 91 endobj
97 92
98 %% Original object ID: 7 0 93 %% Original object ID: 7 0
99 -10 0 obj 94 +9 0 obj
100 [ 95 [
101 /PDF 96 /PDF
102 /Text 97 /Text
@@ -104,24 +99,23 @@ endobj @@ -104,24 +99,23 @@ endobj
104 endobj 99 endobj
105 100
106 xref 101 xref
107 -0 11 102 +0 10
108 0000000000 65535 f 103 0000000000 65535 f
109 0000000052 00000 n 104 0000000052 00000 n
110 0000000133 00000 n 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 trailer << 113 trailer <<
120 /QTest 2 0 R 114 /QTest 2 0 R
121 /Root 1 0 R 115 /Root 1 0 R
122 - /Size 11 116 + /Size 10
123 /ID [<06c2c8fc54c5f9cc9246898e1e1a7146><31415926535897932384626433832795>] 117 /ID [<06c2c8fc54c5f9cc9246898e1e1a7146><31415926535897932384626433832795>]
124 >> 118 >>
125 startxref 119 startxref
126 -1014 120 +962
127 %%EOF 121 %%EOF
qpdf/qtest/qpdf/json-changed-good13.pdf
@@ -14,14 +14,14 @@ endobj @@ -14,14 +14,14 @@ endobj
14 2 0 obj 14 2 0 obj
15 << 15 <<
16 /dangling-ref-for-json-test [ 16 /dangling-ref-for-json-test [
17 - 4 0 R 17 + null
18 ] 18 ]
19 /hex#20strings [ 19 /hex#20strings [
20 (Potato) 20 (Potato)
21 <01020300040560> 21 <01020300040560>
22 (AB) 22 (AB)
23 ] 23 ]
24 - /indirect 5 0 R 24 + /indirect 4 0 R
25 /names [ 25 /names [
26 /nesting 26 /nesting
27 /hex#20strings 27 /hex#20strings
@@ -71,27 +71,22 @@ endobj @@ -71,27 +71,22 @@ endobj
71 << 71 <<
72 /Count 1 72 /Count 1
73 /Kids [ 73 /Kids [
74 - 6 0 R 74 + 5 0 R
75 ] 75 ]
76 /Type /Pages 76 /Type /Pages
77 >> 77 >>
78 endobj 78 endobj
79 79
80 -%% Original object ID: 9 0  
81 -4 0 obj  
82 -null  
83 -endobj  
84 -  
85 %% Original object ID: 8 0 80 %% Original object ID: 8 0
86 -5 0 obj 81 +4 0 obj
87 (hello) 82 (hello)
88 endobj 83 endobj
89 84
90 %% Page 1 85 %% Page 1
91 %% Original object ID: 3 0 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 /MediaBox [ 90 /MediaBox [
96 0 91 0
97 0 92 0
@@ -101,9 +96,9 @@ endobj @@ -101,9 +96,9 @@ endobj
101 /Parent 3 0 R 96 /Parent 3 0 R
102 /Resources << 97 /Resources <<
103 /Font << 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 /Type /Page 103 /Type /Page
109 >> 104 >>
@@ -111,9 +106,9 @@ endobj @@ -111,9 +106,9 @@ endobj
111 106
112 %% Contents for page 1 107 %% Contents for page 1
113 %% Original object ID: 4 0 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 stream 113 stream
119 BT 114 BT
@@ -124,12 +119,12 @@ ET @@ -124,12 +119,12 @@ ET
124 endstream 119 endstream
125 endobj 120 endobj
126 121
127 -8 0 obj 122 +7 0 obj
128 44 123 44
129 endobj 124 endobj
130 125
131 %% Original object ID: 6 0 126 %% Original object ID: 6 0
132 -9 0 obj 127 +8 0 obj
133 << 128 <<
134 /BaseFont /Helvetica 129 /BaseFont /Helvetica
135 /Encoding /WinAnsiEncoding 130 /Encoding /WinAnsiEncoding
@@ -140,7 +135,7 @@ endobj @@ -140,7 +135,7 @@ endobj
140 endobj 135 endobj
141 136
142 %% Original object ID: 5 0 137 %% Original object ID: 5 0
143 -10 0 obj 138 +9 0 obj
144 [ 139 [
145 /PDF 140 /PDF
146 /Text 141 /Text
@@ -148,24 +143,23 @@ endobj @@ -148,24 +143,23 @@ endobj
148 endobj 143 endobj
149 144
150 xref 145 xref
151 -0 11 146 +0 10
152 0000000000 65535 f 147 0000000000 65535 f
153 0000000052 00000 n 148 0000000052 00000 n
154 0000000133 00000 n 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 trailer << 157 trailer <<
164 /QTest 2 0 R 158 /QTest 2 0 R
165 /Root 1 0 R 159 /Root 1 0 R
166 - /Size 11 160 + /Size 10
167 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] 161 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
168 >> 162 >>
169 startxref 163 startxref
170 -1529 164 +1478
171 %%EOF 165 %%EOF
qpdf/qtest/qpdf/replace-with-stream-updated.pdf
@@ -14,14 +14,14 @@ endobj @@ -14,14 +14,14 @@ endobj
14 2 0 obj 14 2 0 obj
15 << 15 <<
16 /dangling-ref-for-json-test [ 16 /dangling-ref-for-json-test [
17 - 4 0 R 17 + null
18 ] 18 ]
19 /hex#20strings [ 19 /hex#20strings [
20 (Potato) 20 (Potato)
21 <01020300040560> 21 <01020300040560>
22 (AB) 22 (AB)
23 ] 23 ]
24 - /indirect 5 0 R 24 + /indirect 4 0 R
25 /names [ 25 /names [
26 /nesting 26 /nesting
27 /hex#20strings 27 /hex#20strings
@@ -71,37 +71,32 @@ endobj @@ -71,37 +71,32 @@ endobj
71 << 71 <<
72 /Count 1 72 /Count 1
73 /Kids [ 73 /Kids [
74 - 7 0 R 74 + 6 0 R
75 ] 75 ]
76 /Type /Pages 76 /Type /Pages
77 >> 77 >>
78 endobj 78 endobj
79 79
80 -%% Original object ID: 9 0  
81 -4 0 obj  
82 -null  
83 -endobj  
84 -  
85 %% Original object ID: 8 0 80 %% Original object ID: 8 0
86 -5 0 obj 81 +4 0 obj
87 << 82 <<
88 /K /V 83 /K /V
89 - /Length 6 0 R 84 + /Length 5 0 R
90 >> 85 >>
91 stream 86 stream
92 new-stream-here 87 new-stream-here
93 endstream 88 endstream
94 endobj 89 endobj
95 90
96 -6 0 obj 91 +5 0 obj
97 16 92 16
98 endobj 93 endobj
99 94
100 %% Page 1 95 %% Page 1
101 %% Original object ID: 3 0 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 /MediaBox [ 100 /MediaBox [
106 0 101 0
107 0 102 0
@@ -111,9 +106,9 @@ endobj @@ -111,9 +106,9 @@ endobj
111 /Parent 3 0 R 106 /Parent 3 0 R
112 /Resources << 107 /Resources <<
113 /Font << 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 /Type /Page 113 /Type /Page
119 >> 114 >>
@@ -121,9 +116,9 @@ endobj @@ -121,9 +116,9 @@ endobj
121 116
122 %% Contents for page 1 117 %% Contents for page 1
123 %% Original object ID: 4 0 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 stream 123 stream
129 BT 124 BT
@@ -134,12 +129,12 @@ ET @@ -134,12 +129,12 @@ ET
134 endstream 129 endstream
135 endobj 130 endobj
136 131
137 -9 0 obj 132 +8 0 obj
138 44 133 44
139 endobj 134 endobj
140 135
141 %% Original object ID: 6 0 136 %% Original object ID: 6 0
142 -10 0 obj 137 +9 0 obj
143 << 138 <<
144 /BaseFont /Helvetica 139 /BaseFont /Helvetica
145 /Encoding /WinAnsiEncoding 140 /Encoding /WinAnsiEncoding
@@ -150,7 +145,7 @@ endobj @@ -150,7 +145,7 @@ endobj
150 endobj 145 endobj
151 146
152 %% Original object ID: 5 0 147 %% Original object ID: 5 0
153 -11 0 obj 148 +10 0 obj
154 [ 149 [
155 /PDF 150 /PDF
156 /Text 151 /Text
@@ -158,25 +153,24 @@ endobj @@ -158,25 +153,24 @@ endobj
158 endobj 153 endobj
159 154
160 xref 155 xref
161 -0 12 156 +0 11
162 0000000000 65535 f 157 0000000000 65535 f
163 0000000052 00000 n 158 0000000052 00000 n
164 0000000133 00000 n 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 trailer << 168 trailer <<
175 /QTest 2 0 R 169 /QTest 2 0 R
176 /Root 1 0 R 170 /Root 1 0 R
177 - /Size 12 171 + /Size 11
178 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] 172 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
179 >> 173 >>
180 startxref 174 startxref
181 -1609 175 +1558
182 %%EOF 176 %%EOF
qpdf/qtest/qpdf/update-stream-data-updated.pdf
@@ -14,14 +14,14 @@ endobj @@ -14,14 +14,14 @@ endobj
14 2 0 obj 14 2 0 obj
15 << 15 <<
16 /dangling-ref-for-json-test [ 16 /dangling-ref-for-json-test [
17 - 4 0 R 17 + null
18 ] 18 ]
19 /hex#20strings [ 19 /hex#20strings [
20 (Potato) 20 (Potato)
21 <01020300040560> 21 <01020300040560>
22 (AB) 22 (AB)
23 ] 23 ]
24 - /indirect 5 0 R 24 + /indirect 4 0 R
25 /names [ 25 /names [
26 /nesting 26 /nesting
27 /hex#20strings 27 /hex#20strings
@@ -71,27 +71,22 @@ endobj @@ -71,27 +71,22 @@ endobj
71 << 71 <<
72 /Count 1 72 /Count 1
73 /Kids [ 73 /Kids [
74 - 6 0 R 74 + 5 0 R
75 ] 75 ]
76 /Type /Pages 76 /Type /Pages
77 >> 77 >>
78 endobj 78 endobj
79 79
80 -%% Original object ID: 9 0  
81 -4 0 obj  
82 -null  
83 -endobj  
84 -  
85 %% Original object ID: 8 0 80 %% Original object ID: 8 0
86 -5 0 obj 81 +4 0 obj
87 (hello) 82 (hello)
88 endobj 83 endobj
89 84
90 %% Page 1 85 %% Page 1
91 %% Original object ID: 3 0 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 /MediaBox [ 90 /MediaBox [
96 0 91 0
97 0 92 0
@@ -101,9 +96,9 @@ endobj @@ -101,9 +96,9 @@ endobj
101 /Parent 3 0 R 96 /Parent 3 0 R
102 /Resources << 97 /Resources <<
103 /Font << 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 /Type /Page 103 /Type /Page
109 >> 104 >>
@@ -111,9 +106,9 @@ endobj @@ -111,9 +106,9 @@ endobj
111 106
112 %% Contents for page 1 107 %% Contents for page 1
113 %% Original object ID: 4 0 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 stream 113 stream
119 BT 114 BT
@@ -124,12 +119,12 @@ ET @@ -124,12 +119,12 @@ ET
124 endstream 119 endstream
125 endobj 120 endobj
126 121
127 -8 0 obj 122 +7 0 obj
128 43 123 43
129 endobj 124 endobj
130 125
131 %% Original object ID: 6 0 126 %% Original object ID: 6 0
132 -9 0 obj 127 +8 0 obj
133 << 128 <<
134 /BaseFont /Helvetica 129 /BaseFont /Helvetica
135 /Encoding /WinAnsiEncoding 130 /Encoding /WinAnsiEncoding
@@ -140,7 +135,7 @@ endobj @@ -140,7 +135,7 @@ endobj
140 endobj 135 endobj
141 136
142 %% Original object ID: 5 0 137 %% Original object ID: 5 0
143 -10 0 obj 138 +9 0 obj
144 [ 139 [
145 /PDF 140 /PDF
146 /Text 141 /Text
@@ -148,24 +143,23 @@ endobj @@ -148,24 +143,23 @@ endobj
148 endobj 143 endobj
149 144
150 xref 145 xref
151 -0 11 146 +0 10
152 0000000000 65535 f 147 0000000000 65535 f
153 0000000052 00000 n 148 0000000052 00000 n
154 0000000133 00000 n 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 trailer << 157 trailer <<
164 /QTest 2 0 R 158 /QTest 2 0 R
165 /Root 1 0 R 159 /Root 1 0 R
166 - /Size 11 160 + /Size 10
167 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] 161 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
168 >> 162 >>
169 startxref 163 startxref
170 -1532 164 +1481
171 %%EOF 165 %%EOF
qpdf/qtest/qpdf/update-stream-dict-only-updated.pdf
@@ -14,14 +14,14 @@ endobj @@ -14,14 +14,14 @@ endobj
14 2 0 obj 14 2 0 obj
15 << 15 <<
16 /dangling-ref-for-json-test [ 16 /dangling-ref-for-json-test [
17 - 4 0 R 17 + null
18 ] 18 ]
19 /hex#20strings [ 19 /hex#20strings [
20 (Potato) 20 (Potato)
21 <01020300040560> 21 <01020300040560>
22 (AB) 22 (AB)
23 ] 23 ]
24 - /indirect 5 0 R 24 + /indirect 4 0 R
25 /names [ 25 /names [
26 /nesting 26 /nesting
27 /hex#20strings 27 /hex#20strings
@@ -71,27 +71,22 @@ endobj @@ -71,27 +71,22 @@ endobj
71 << 71 <<
72 /Count 1 72 /Count 1
73 /Kids [ 73 /Kids [
74 - 6 0 R 74 + 5 0 R
75 ] 75 ]
76 /Type /Pages 76 /Type /Pages
77 >> 77 >>
78 endobj 78 endobj
79 79
80 -%% Original object ID: 9 0  
81 -4 0 obj  
82 -null  
83 -endobj  
84 -  
85 %% Original object ID: 8 0 80 %% Original object ID: 8 0
86 -5 0 obj 81 +4 0 obj
87 (hello) 82 (hello)
88 endobj 83 endobj
89 84
90 %% Page 1 85 %% Page 1
91 %% Original object ID: 3 0 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 /MediaBox [ 90 /MediaBox [
96 0 91 0
97 0 92 0
@@ -101,9 +96,9 @@ endobj @@ -101,9 +96,9 @@ endobj
101 /Parent 3 0 R 96 /Parent 3 0 R
102 /Resources << 97 /Resources <<
103 /Font << 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 /Type /Page 103 /Type /Page
109 >> 104 >>
@@ -111,10 +106,10 @@ endobj @@ -111,10 +106,10 @@ endobj
111 106
112 %% Contents for page 1 107 %% Contents for page 1
113 %% Original object ID: 4 0 108 %% Original object ID: 4 0
114 -7 0 obj 109 +6 0 obj
115 << 110 <<
116 /Potato (salad) 111 /Potato (salad)
117 - /Length 8 0 R 112 + /Length 7 0 R
118 >> 113 >>
119 stream 114 stream
120 BT 115 BT
@@ -125,12 +120,12 @@ ET @@ -125,12 +120,12 @@ ET
125 endstream 120 endstream
126 endobj 121 endobj
127 122
128 -8 0 obj 123 +7 0 obj
129 44 124 44
130 endobj 125 endobj
131 126
132 %% Original object ID: 6 0 127 %% Original object ID: 6 0
133 -9 0 obj 128 +8 0 obj
134 << 129 <<
135 /BaseFont /Helvetica 130 /BaseFont /Helvetica
136 /Encoding /WinAnsiEncoding 131 /Encoding /WinAnsiEncoding
@@ -141,7 +136,7 @@ endobj @@ -141,7 +136,7 @@ endobj
141 endobj 136 endobj
142 137
143 %% Original object ID: 5 0 138 %% Original object ID: 5 0
144 -10 0 obj 139 +9 0 obj
145 [ 140 [
146 /PDF 141 /PDF
147 /Text 142 /Text
@@ -149,24 +144,23 @@ endobj @@ -149,24 +144,23 @@ endobj
149 endobj 144 endobj
150 145
151 xref 146 xref
152 -0 11 147 +0 10
153 0000000000 65535 f 148 0000000000 65535 f
154 0000000052 00000 n 149 0000000052 00000 n
155 0000000133 00000 n 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 trailer << 158 trailer <<
165 /QTest 2 0 R 159 /QTest 2 0 R
166 /Root 1 0 R 160 /Root 1 0 R
167 - /Size 11 161 + /Size 10
168 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] 162 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>]
169 >> 163 >>
170 startxref 164 startxref
171 -1551 165 +1500
172 %%EOF 166 %%EOF