diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index e3238fd4..6e567569 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -819,7 +819,8 @@ class QPDF } }; - // The ParseGuard class allows QPDFParser to detect re-entrant parsing. + // The ParseGuard class allows QPDFParser to detect re-entrant parsing. It also provides + // special access to allow the parser to create unresolved objects and dangling references. class ParseGuard { friend class QPDFParser; @@ -832,6 +833,13 @@ class QPDF qpdf->inParse(true); } } + + static std::shared_ptr + getObject(QPDF* qpdf, int id, int gen, bool parse_pdf) + { + return qpdf->getObjectForParser(id, gen, parse_pdf); + } + ~ParseGuard() { if (qpdf) { @@ -900,8 +908,8 @@ class QPDF } ObjCache( std::shared_ptr object, - qpdf_offset_t end_before_space, - qpdf_offset_t end_after_space) : + qpdf_offset_t end_before_space = 0, + qpdf_offset_t end_after_space = 0) : object(object), end_before_space(end_before_space), end_after_space(end_after_space) @@ -1065,13 +1073,14 @@ class QPDF QPDFObject* resolve(QPDFObjGen og); void resolveObjectsInStream(int obj_stream_number); void stopOnError(std::string const& message); - QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og); QPDFObjectHandle reserveStream(QPDFObjGen const& og); QPDFObjGen nextObjGen(); QPDFObjectHandle newIndirect(QPDFObjGen const&, std::shared_ptr const&); QPDFObjectHandle makeIndirectFromQPDFObject(std::shared_ptr const& obj); bool isCached(QPDFObjGen const& og); bool isUnresolved(QPDFObjGen const& og); + std::shared_ptr getObjectForParser(int id, int gen, bool parse_pdf); + std::shared_ptr getObjectForJSON(int id, int gen); void removeObject(QPDFObjGen og); void updateCache( QPDFObjGen const& og, diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 93d50829..c5f8ee74 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -654,9 +654,11 @@ QPDF::reconstruct_xref(QPDFExc& e) } check_warnings(); if (!m->parsed) { + m->parsed = true; getAllPages(); check_warnings(); if (m->all_pages.empty()) { + m->parsed = false; throw damagedPDF("", 0, "unable to find any pages while recovering damaged file"); } } @@ -2095,31 +2097,53 @@ QPDF::newStream(std::string const& data) return result; } -QPDFObjectHandle -QPDF::reserveObjectIfNotExists(QPDFObjGen const& og) -{ - if (!isCached(og) && m->xref_table.count(og) == 0) { - updateCache(og, QPDF_Reserved::create(), -1, -1); - return newIndirect(og, m->obj_cache[og].object); - } else { - return getObject(og); - } -} - QPDFObjectHandle QPDF::reserveStream(QPDFObjGen const& og) { return {QPDF_Stream::create(this, og, QPDFObjectHandle::newDictionary(), 0, 0)}; } +std::shared_ptr +QPDF::getObjectForParser(int id, int gen, bool parse_pdf) +{ + // This method is called by the parser and therefore must not resolve any objects. + auto og = QPDFObjGen(id, gen); + if (auto iter = m->obj_cache.find(og); iter != m->obj_cache.end()) { + return iter->second.object; + } + if (m->xref_table.count(og) || !m->parsed) { + return m->obj_cache.insert({og, QPDF_Unresolved::create(this, og)}).first->second.object; + } + if (parse_pdf) { + return QPDF_Null::create(); + } + return m->obj_cache.insert({og, QPDF_Null::create(this, og)}).first->second.object; +} + +std::shared_ptr +QPDF::getObjectForJSON(int id, int gen) +{ + auto og = QPDFObjGen(id, gen); + auto [it, inserted] = m->obj_cache.try_emplace(og); + auto& obj = it->second.object; + if (inserted) { + obj = (m->parsed && !m->xref_table.count(og)) ? QPDF_Null::create(this, og) + : QPDF_Unresolved::create(this, og); + } + return obj; +} + QPDFObjectHandle QPDF::getObject(QPDFObjGen const& og) { - // This method is called by the parser and therefore must not resolve any objects. - if (!isCached(og)) { - m->obj_cache[og] = ObjCache(QPDF_Unresolved::create(this, og), -1, -1); + if (auto it = m->obj_cache.find(og); it != m->obj_cache.end()) { + return {it->second.object}; + } else if (m->parsed && !m->xref_table.count(og)) { + return QPDF_Null::create(); + } else { + auto result = m->obj_cache.try_emplace(og, QPDF_Unresolved::create(this, og), -1, -1); + return {result.first->second.object}; } - return newIndirect(og, m->obj_cache[og].object); } QPDFObjectHandle diff --git a/libqpdf/QPDFParser.cc b/libqpdf/QPDFParser.cc index 56448364..08f94c64 100644 --- a/libqpdf/QPDFParser.cc +++ b/libqpdf/QPDFParser.cc @@ -166,10 +166,7 @@ QPDFParser::parseRemainder(bool content_stream) auto id = QIntC::to_int(int_buffer[(int_count - 1) % 2]); auto gen = QIntC::to_int(int_buffer[(int_count) % 2]); if (!(id < 1 || gen < 0 || gen >= 65535)) { - // This action has the desirable side effect of causing dangling references - // (references to indirect objects that don't appear in the PDF) in any parsed - // object to appear in the object cache. - add(std::move(context->getObject(id, gen).obj)); + add(QPDF::ParseGuard::getObject(context, id, gen, parse_pdf)); } else { QTC::TC("qpdf", "QPDFParser invalid objgen"); addNull(); diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index b8b25fa0..d7ac7134 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -1237,7 +1237,7 @@ bool QPDFWriter::willFilterStream( QPDFObjectHandle stream, bool& compress_stream, // out only - bool& is_metadata, // out only + bool& is_metadata, // out only std::shared_ptr* stream_data) { compress_stream = false; diff --git a/libqpdf/QPDF_Null.cc b/libqpdf/QPDF_Null.cc index fa4b6cab..9b92c911 100644 --- a/libqpdf/QPDF_Null.cc +++ b/libqpdf/QPDF_Null.cc @@ -3,15 +3,15 @@ #include #include -QPDF_Null::QPDF_Null() : - QPDFValue(::ot_null, "null") +QPDF_Null::QPDF_Null(QPDF* qpdf, QPDFObjGen og) : + QPDFValue(::ot_null, "null", qpdf, og) { } std::shared_ptr -QPDF_Null::create() +QPDF_Null::create(QPDF* qpdf, QPDFObjGen og) { - return do_create(new QPDF_Null()); + return do_create(new QPDF_Null(qpdf, og)); } std::shared_ptr diff --git a/libqpdf/QPDF_json.cc b/libqpdf/QPDF_json.cc index dd4672fe..26814f5d 100644 --- a/libqpdf/QPDF_json.cc +++ b/libqpdf/QPDF_json.cc @@ -240,11 +240,6 @@ class QPDF::JSONReactor: public JSON::Reactor descr(std::make_shared( QPDFValue::JSON_Descr(std::make_shared(is->getName()), ""))) { - for (auto& oc: pdf.m->obj_cache) { - if (oc.second.object->getTypeCode() == ::ot_reserved) { - reserved.insert(oc.first); - } - } } ~JSONReactor() override = default; void dictionaryStart() override; @@ -305,7 +300,6 @@ class QPDF::JSONReactor: public JSON::Reactor bool saw_data{false}; bool saw_datafile{false}; bool this_stream_needs_data{false}; - std::set reserved; std::vector stack; QPDFObjectHandle next_obj; state_e next_state{st_top}; @@ -416,16 +410,6 @@ QPDF::JSONReactor::containerEnd(JSON const& value) } } } - } else if (from_state == st_qpdf) { - // Handle dangling indirect object references which the PDF spec says to treat as nulls. - // It's tempting to make this an error, but that would be wrong since valid input files may - // have these. - for (auto& oc: pdf.m->obj_cache) { - if (oc.second.object->getTypeCode() == ::ot_reserved && reserved.count(oc.first) == 0) { - QTC::TC("qpdf", "QPDF_json non-trivial null reserved"); - pdf.updateCache(oc.first, QPDF_Null::create(), -1, -1); - } - } } if (!stack.empty()) { auto state = stack.back().state; @@ -565,7 +549,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) } else if (is_obj_key(key, obj, gen)) { this->cur_object = key; if (setNextStateIfDictionary(key, value, st_object_top)) { - next_obj = pdf.reserveObjectIfNotExists(QPDFObjGen(obj, gen)); + next_obj = pdf.getObjectForJSON(obj, gen); } } else { QTC::TC("qpdf", "QPDF_json bad object key"); @@ -767,7 +751,7 @@ QPDF::JSONReactor::makeObject(JSON const& value) int gen = 0; std::string str; if (is_indirect_object(str_v, obj, gen)) { - result = pdf.reserveObjectIfNotExists(QPDFObjGen(obj, gen)); + result = pdf.getObjectForJSON(obj, gen); } else if (is_unicode_string(str_v, str)) { result = QPDFObjectHandle::newUnicodeString(str); } else if (is_binary_string(str_v, str)) { diff --git a/libqpdf/qpdf/QPDFParser.hh b/libqpdf/qpdf/QPDFParser.hh index d6b76a21..e036b022 100644 --- a/libqpdf/qpdf/QPDFParser.hh +++ b/libqpdf/qpdf/QPDFParser.hh @@ -24,7 +24,8 @@ class QPDFParser decrypter(decrypter), context(context), description(std::make_shared( - std::string(input->getName() + ", " + object_description + " at offset $PO"))) + std::string(input->getName() + ", " + object_description + " at offset $PO"))), + parse_pdf(parse_pdf) { } virtual ~QPDFParser() = default; @@ -77,6 +78,8 @@ class QPDFParser QPDFObjectHandle::StringDecrypter* decrypter; QPDF* context; std::shared_ptr description; + bool parse_pdf; + std::vector stack; StackFrame* frame; // Number of recent bad tokens. diff --git a/libqpdf/qpdf/QPDF_Null.hh b/libqpdf/qpdf/QPDF_Null.hh index fc6e0b5f..231ea669 100644 --- a/libqpdf/qpdf/QPDF_Null.hh +++ b/libqpdf/qpdf/QPDF_Null.hh @@ -7,7 +7,7 @@ class QPDF_Null: public QPDFValue { public: ~QPDF_Null() override = default; - static std::shared_ptr create(); + static std::shared_ptr create(QPDF* qpdf = nullptr, QPDFObjGen og = QPDFObjGen()); static std::shared_ptr create( std::shared_ptr parent, std::string_view const& static_descr, @@ -21,7 +21,7 @@ class QPDF_Null: public QPDFValue void writeJSON(int json_version, JSON::Writer& p) override; private: - QPDF_Null(); + QPDF_Null(QPDF* qpdf = nullptr, QPDFObjGen og = QPDFObjGen()); }; #endif // QPDF_NULL_HH diff --git a/libtests/sparse_array.cc b/libtests/sparse_array.cc index 47fe8c26..9405a89b 100644 --- a/libtests/sparse_array.cc +++ b/libtests/sparse_array.cc @@ -90,17 +90,17 @@ main() obj = QPDF_Array::create({10, "null"_qpdf.getObj()}, true); QPDF_Array& b = *obj->as(); - b.setAt(5, pdf.getObject(5, 0)); + b.setAt(5, pdf.newIndirectNull()); b.setAt(7, "[0 1 2 3]"_qpdf); assert(b.at(3).isNull()); assert(b.at(8).isNull()); assert(b.at(5).isIndirect()); - assert(b.unparse() == "[ null null null null null 5 0 R null [ 0 1 2 3 ] null null ]"); + assert(b.unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); auto c = b.copy(true); auto d = b.copy(false); b.at(7).setArrayItem(2, "42"_qpdf); - assert(c->unparse() == "[ null null null null null 5 0 R null [ 0 1 42 3 ] null null ]"); - assert(d->unparse() == "[ null null null null null 5 0 R null [ 0 1 2 3 ] null null ]"); + assert(c->unparse() == "[ null null null null null 3 0 R null [ 0 1 42 3 ] null null ]"); + assert(d->unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); try { b.setAt(3, {}); diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 3ed710d0..733a0169 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -675,7 +675,6 @@ QPDF_json ignore second-level key 0 QPDF_json ignore unknown key in object_top 0 QPDF_json ignore unknown key in trailer 0 QPDF_json ignore unknown key in stream 0 -QPDF_json non-trivial null reserved 0 QPDF_json data and datafile 0 QPDF_json no stream data in update mode 0 QPDF_json updating existing stream 0 diff --git a/qpdf/qtest/qpdf/dangling-bad-xref-dangling-out.pdf b/qpdf/qtest/qpdf/dangling-bad-xref-dangling-out.pdf index db2f38d1..6f34f104 100644 Binary files a/qpdf/qtest/qpdf/dangling-bad-xref-dangling-out.pdf and b/qpdf/qtest/qpdf/dangling-bad-xref-dangling-out.pdf differ diff --git a/qpdf/qtest/qpdf/dangling-bad-xref-dangling.out b/qpdf/qtest/qpdf/dangling-bad-xref-dangling.out index 05221c72..6b96e2a1 100644 --- a/qpdf/qtest/qpdf/dangling-bad-xref-dangling.out +++ b/qpdf/qtest/qpdf/dangling-bad-xref-dangling.out @@ -1,7 +1,7 @@ WARNING: dangling-bad-xref.pdf: file is damaged WARNING: dangling-bad-xref.pdf (object 7 0, offset 10000): expected n n obj WARNING: dangling-bad-xref.pdf: Attempting to reconstruct cross-reference table -new object: 13 0 R +new object: 12 0 R all objects 1 0 R 2 0 R @@ -10,10 +10,6 @@ all objects 5 0 R 6 0 R 7 0 R -8 0 R -9 0 R -10 0 R 11 0 R 12 0 R -13 0 R test 53 done diff --git a/qpdf/qtest/qpdf/dangling-refs-dangling-out.pdf b/qpdf/qtest/qpdf/dangling-refs-dangling-out.pdf index 75c5e4db..5b64f777 100644 Binary files a/qpdf/qtest/qpdf/dangling-refs-dangling-out.pdf and b/qpdf/qtest/qpdf/dangling-refs-dangling-out.pdf differ diff --git a/qpdf/qtest/qpdf/dangling-refs-dangling.out b/qpdf/qtest/qpdf/dangling-refs-dangling.out index a41cd59c..4ba36f50 100644 --- a/qpdf/qtest/qpdf/dangling-refs-dangling.out +++ b/qpdf/qtest/qpdf/dangling-refs-dangling.out @@ -1,4 +1,4 @@ -new object: 11 0 R +new object: 8 0 R all objects 1 0 R 2 0 R @@ -8,7 +8,4 @@ all objects 6 0 R 7 0 R 8 0 R -9 0 R -10 0 R -11 0 R test 53 done diff --git a/qpdf/qtest/qpdf/good13.out b/qpdf/qtest/qpdf/good13.out index e6cb1d32..adc2b24b 100644 --- a/qpdf/qtest/qpdf/good13.out +++ b/qpdf/qtest/qpdf/good13.out @@ -7,5 +7,5 @@ /nesting is direct /strings is direct unparse: 7 0 R -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) ] >> +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) ] >> test 1 done diff --git a/qpdf/qtest/qpdf/good13.qdf b/qpdf/qtest/qpdf/good13.qdf index 236ee585..b6c1507c 100644 --- a/qpdf/qtest/qpdf/good13.qdf +++ b/qpdf/qtest/qpdf/good13.qdf @@ -14,14 +14,14 @@ endobj 2 0 obj << /dangling-ref-for-json-test [ - 4 0 R + null ] /hex#20strings [ (Potato) <01020300040560> (AB) ] - /indirect 5 0 R + /indirect 4 0 R /names [ /nesting /hex#20strings @@ -71,27 +71,22 @@ endobj << /Count 1 /Kids [ - 6 0 R + 5 0 R ] /Type /Pages >> endobj -%% Original object ID: 9 0 -4 0 obj -null -endobj - %% Original object ID: 8 0 -5 0 obj +4 0 obj (hello) endobj %% Page 1 %% Original object ID: 3 0 -6 0 obj +5 0 obj << - /Contents 7 0 R + /Contents 6 0 R /MediaBox [ 0 0 @@ -101,9 +96,9 @@ endobj /Parent 3 0 R /Resources << /Font << - /F1 9 0 R + /F1 8 0 R >> - /ProcSet 10 0 R + /ProcSet 9 0 R >> /Type /Page >> @@ -111,9 +106,9 @@ endobj %% Contents for page 1 %% Original object ID: 4 0 -7 0 obj +6 0 obj << - /Length 8 0 R + /Length 7 0 R >> stream BT @@ -124,12 +119,12 @@ ET endstream endobj -8 0 obj +7 0 obj 44 endobj %% Original object ID: 6 0 -9 0 obj +8 0 obj << /BaseFont /Helvetica /Encoding /WinAnsiEncoding @@ -140,7 +135,7 @@ endobj endobj %% Original object ID: 5 0 -10 0 obj +9 0 obj [ /PDF /Text @@ -148,24 +143,23 @@ endobj endobj xref -0 11 +0 10 0000000000 65535 f 0000000052 00000 n 0000000133 00000 n -0000000756 00000 n -0000000855 00000 n -0000000903 00000 n -0000000964 00000 n -0000001207 00000 n -0000001306 00000 n -0000001352 00000 n -0000001497 00000 n +0000000755 00000 n +0000000854 00000 n +0000000915 00000 n +0000001157 00000 n +0000001256 00000 n +0000001302 00000 n +0000001447 00000 n trailer << /QTest 2 0 R /Root 1 0 R - /Size 11 + /Size 10 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >> startxref -1533 +1482 %%EOF diff --git a/qpdf/qtest/qpdf/good21.out b/qpdf/qtest/qpdf/good21.out index ffcdf2a7..39e1271c 100644 --- a/qpdf/qtest/qpdf/good21.out +++ b/qpdf/qtest/qpdf/good21.out @@ -5,7 +5,7 @@ item 2 is direct item 3 is indirect item 4 is direct - item 5 is indirect + item 5 is direct unparse: 9 0 R -unparseResolved: [ /literal null /indirect 8 0 R /undefined 10 0 R ] +unparseResolved: [ /literal null /indirect 8 0 R /undefined null ] test 1 done diff --git a/qpdf/qtest/qpdf/good21.qdf b/qpdf/qtest/qpdf/good21.qdf index 49bff240..55a65eb4 100644 --- a/qpdf/qtest/qpdf/good21.qdf +++ b/qpdf/qtest/qpdf/good21.qdf @@ -18,7 +18,7 @@ endobj /indirect 4 0 R /undefined - 5 0 R + null ] endobj @@ -27,7 +27,7 @@ endobj << /Count 1 /Kids [ - 6 0 R + 5 0 R ] /Type /Pages >> @@ -38,16 +38,11 @@ endobj null endobj -%% Original object ID: 10 0 -5 0 obj -null -endobj - %% Page 1 %% Original object ID: 3 0 -6 0 obj +5 0 obj << - /Contents 7 0 R + /Contents 6 0 R /MediaBox [ 0 0 @@ -57,9 +52,9 @@ endobj /Parent 3 0 R /Resources << /Font << - /F1 9 0 R + /F1 8 0 R >> - /ProcSet 10 0 R + /ProcSet 9 0 R >> /Type /Page >> @@ -67,9 +62,9 @@ endobj %% Contents for page 1 %% Original object ID: 4 0 -7 0 obj +6 0 obj << - /Length 8 0 R + /Length 7 0 R >> stream BT @@ -80,12 +75,12 @@ ET endstream endobj -8 0 obj +7 0 obj 44 endobj %% Original object ID: 6 0 -9 0 obj +8 0 obj << /BaseFont /Helvetica /Encoding /WinAnsiEncoding @@ -96,7 +91,7 @@ endobj endobj %% Original object ID: 7 0 -10 0 obj +9 0 obj [ /PDF /Text @@ -104,24 +99,23 @@ endobj endobj xref -0 11 +0 10 0000000000 65535 f 0000000052 00000 n 0000000133 00000 n -0000000239 00000 n -0000000338 00000 n -0000000387 00000 n -0000000445 00000 n -0000000688 00000 n -0000000787 00000 n -0000000833 00000 n -0000000978 00000 n +0000000238 00000 n +0000000337 00000 n +0000000395 00000 n +0000000637 00000 n +0000000736 00000 n +0000000782 00000 n +0000000927 00000 n trailer << /QTest 2 0 R /Root 1 0 R - /Size 11 + /Size 10 /ID [<06c2c8fc54c5f9cc9246898e1e1a7146><31415926535897932384626433832795>] >> startxref -1014 +962 %%EOF diff --git a/qpdf/qtest/qpdf/json-changed-good13.pdf b/qpdf/qtest/qpdf/json-changed-good13.pdf index 2c25334c..b0cb9cc5 100644 --- a/qpdf/qtest/qpdf/json-changed-good13.pdf +++ b/qpdf/qtest/qpdf/json-changed-good13.pdf @@ -14,14 +14,14 @@ endobj 2 0 obj << /dangling-ref-for-json-test [ - 4 0 R + null ] /hex#20strings [ (Potato) <01020300040560> (AB) ] - /indirect 5 0 R + /indirect 4 0 R /names [ /nesting /hex#20strings @@ -71,27 +71,22 @@ endobj << /Count 1 /Kids [ - 6 0 R + 5 0 R ] /Type /Pages >> endobj -%% Original object ID: 9 0 -4 0 obj -null -endobj - %% Original object ID: 8 0 -5 0 obj +4 0 obj (hello) endobj %% Page 1 %% Original object ID: 3 0 -6 0 obj +5 0 obj << - /Contents 7 0 R + /Contents 6 0 R /MediaBox [ 0 0 @@ -101,9 +96,9 @@ endobj /Parent 3 0 R /Resources << /Font << - /F1 9 0 R + /F1 8 0 R >> - /ProcSet 10 0 R + /ProcSet 9 0 R >> /Type /Page >> @@ -111,9 +106,9 @@ endobj %% Contents for page 1 %% Original object ID: 4 0 -7 0 obj +6 0 obj << - /Length 8 0 R + /Length 7 0 R >> stream BT @@ -124,12 +119,12 @@ ET endstream endobj -8 0 obj +7 0 obj 44 endobj %% Original object ID: 6 0 -9 0 obj +8 0 obj << /BaseFont /Helvetica /Encoding /WinAnsiEncoding @@ -140,7 +135,7 @@ endobj endobj %% Original object ID: 5 0 -10 0 obj +9 0 obj [ /PDF /Text @@ -148,24 +143,23 @@ endobj endobj xref -0 11 +0 10 0000000000 65535 f 0000000052 00000 n 0000000133 00000 n -0000000752 00000 n -0000000851 00000 n -0000000899 00000 n -0000000960 00000 n -0000001203 00000 n -0000001302 00000 n -0000001348 00000 n -0000001493 00000 n +0000000751 00000 n +0000000850 00000 n +0000000911 00000 n +0000001153 00000 n +0000001252 00000 n +0000001298 00000 n +0000001443 00000 n trailer << /QTest 2 0 R /Root 1 0 R - /Size 11 + /Size 10 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >> startxref -1529 +1478 %%EOF diff --git a/qpdf/qtest/qpdf/replace-with-stream-updated.pdf b/qpdf/qtest/qpdf/replace-with-stream-updated.pdf index d8dc76a3..a1ec222e 100644 --- a/qpdf/qtest/qpdf/replace-with-stream-updated.pdf +++ b/qpdf/qtest/qpdf/replace-with-stream-updated.pdf @@ -14,14 +14,14 @@ endobj 2 0 obj << /dangling-ref-for-json-test [ - 4 0 R + null ] /hex#20strings [ (Potato) <01020300040560> (AB) ] - /indirect 5 0 R + /indirect 4 0 R /names [ /nesting /hex#20strings @@ -71,37 +71,32 @@ endobj << /Count 1 /Kids [ - 7 0 R + 6 0 R ] /Type /Pages >> endobj -%% Original object ID: 9 0 -4 0 obj -null -endobj - %% Original object ID: 8 0 -5 0 obj +4 0 obj << /K /V - /Length 6 0 R + /Length 5 0 R >> stream new-stream-here endstream endobj -6 0 obj +5 0 obj 16 endobj %% Page 1 %% Original object ID: 3 0 -7 0 obj +6 0 obj << - /Contents 8 0 R + /Contents 7 0 R /MediaBox [ 0 0 @@ -111,9 +106,9 @@ endobj /Parent 3 0 R /Resources << /Font << - /F1 10 0 R + /F1 9 0 R >> - /ProcSet 11 0 R + /ProcSet 10 0 R >> /Type /Page >> @@ -121,9 +116,9 @@ endobj %% Contents for page 1 %% Original object ID: 4 0 -8 0 obj +7 0 obj << - /Length 9 0 R + /Length 8 0 R >> stream BT @@ -134,12 +129,12 @@ ET endstream endobj -9 0 obj +8 0 obj 44 endobj %% Original object ID: 6 0 -10 0 obj +9 0 obj << /BaseFont /Helvetica /Encoding /WinAnsiEncoding @@ -150,7 +145,7 @@ endobj endobj %% Original object ID: 5 0 -11 0 obj +10 0 obj [ /PDF /Text @@ -158,25 +153,24 @@ endobj endobj xref -0 12 +0 11 0000000000 65535 f 0000000052 00000 n 0000000133 00000 n -0000000756 00000 n -0000000855 00000 n -0000000903 00000 n -0000000982 00000 n -0000001038 00000 n -0000001282 00000 n -0000001381 00000 n -0000001427 00000 n -0000001573 00000 n +0000000755 00000 n +0000000854 00000 n +0000000933 00000 n +0000000989 00000 n +0000001232 00000 n +0000001331 00000 n +0000001377 00000 n +0000001522 00000 n trailer << /QTest 2 0 R /Root 1 0 R - /Size 12 + /Size 11 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >> startxref -1609 +1558 %%EOF diff --git a/qpdf/qtest/qpdf/update-stream-data-updated.pdf b/qpdf/qtest/qpdf/update-stream-data-updated.pdf index 3f9ae74d..7a18211d 100644 --- a/qpdf/qtest/qpdf/update-stream-data-updated.pdf +++ b/qpdf/qtest/qpdf/update-stream-data-updated.pdf @@ -14,14 +14,14 @@ endobj 2 0 obj << /dangling-ref-for-json-test [ - 4 0 R + null ] /hex#20strings [ (Potato) <01020300040560> (AB) ] - /indirect 5 0 R + /indirect 4 0 R /names [ /nesting /hex#20strings @@ -71,27 +71,22 @@ endobj << /Count 1 /Kids [ - 6 0 R + 5 0 R ] /Type /Pages >> endobj -%% Original object ID: 9 0 -4 0 obj -null -endobj - %% Original object ID: 8 0 -5 0 obj +4 0 obj (hello) endobj %% Page 1 %% Original object ID: 3 0 -6 0 obj +5 0 obj << - /Contents 7 0 R + /Contents 6 0 R /MediaBox [ 0 0 @@ -101,9 +96,9 @@ endobj /Parent 3 0 R /Resources << /Font << - /F1 9 0 R + /F1 8 0 R >> - /ProcSet 10 0 R + /ProcSet 9 0 R >> /Type /Page >> @@ -111,9 +106,9 @@ endobj %% Contents for page 1 %% Original object ID: 4 0 -7 0 obj +6 0 obj << - /Length 8 0 R + /Length 7 0 R >> stream BT @@ -124,12 +119,12 @@ ET endstream endobj -8 0 obj +7 0 obj 43 endobj %% Original object ID: 6 0 -9 0 obj +8 0 obj << /BaseFont /Helvetica /Encoding /WinAnsiEncoding @@ -140,7 +135,7 @@ endobj endobj %% Original object ID: 5 0 -10 0 obj +9 0 obj [ /PDF /Text @@ -148,24 +143,23 @@ endobj endobj xref -0 11 +0 10 0000000000 65535 f 0000000052 00000 n 0000000133 00000 n -0000000756 00000 n -0000000855 00000 n -0000000903 00000 n -0000000964 00000 n -0000001207 00000 n -0000001305 00000 n -0000001351 00000 n -0000001496 00000 n +0000000755 00000 n +0000000854 00000 n +0000000915 00000 n +0000001157 00000 n +0000001255 00000 n +0000001301 00000 n +0000001446 00000 n trailer << /QTest 2 0 R /Root 1 0 R - /Size 11 + /Size 10 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >> startxref -1532 +1481 %%EOF diff --git a/qpdf/qtest/qpdf/update-stream-dict-only-updated.pdf b/qpdf/qtest/qpdf/update-stream-dict-only-updated.pdf index f2bd079f..0e3a18bb 100644 --- a/qpdf/qtest/qpdf/update-stream-dict-only-updated.pdf +++ b/qpdf/qtest/qpdf/update-stream-dict-only-updated.pdf @@ -14,14 +14,14 @@ endobj 2 0 obj << /dangling-ref-for-json-test [ - 4 0 R + null ] /hex#20strings [ (Potato) <01020300040560> (AB) ] - /indirect 5 0 R + /indirect 4 0 R /names [ /nesting /hex#20strings @@ -71,27 +71,22 @@ endobj << /Count 1 /Kids [ - 6 0 R + 5 0 R ] /Type /Pages >> endobj -%% Original object ID: 9 0 -4 0 obj -null -endobj - %% Original object ID: 8 0 -5 0 obj +4 0 obj (hello) endobj %% Page 1 %% Original object ID: 3 0 -6 0 obj +5 0 obj << - /Contents 7 0 R + /Contents 6 0 R /MediaBox [ 0 0 @@ -101,9 +96,9 @@ endobj /Parent 3 0 R /Resources << /Font << - /F1 9 0 R + /F1 8 0 R >> - /ProcSet 10 0 R + /ProcSet 9 0 R >> /Type /Page >> @@ -111,10 +106,10 @@ endobj %% Contents for page 1 %% Original object ID: 4 0 -7 0 obj +6 0 obj << /Potato (salad) - /Length 8 0 R + /Length 7 0 R >> stream BT @@ -125,12 +120,12 @@ ET endstream endobj -8 0 obj +7 0 obj 44 endobj %% Original object ID: 6 0 -9 0 obj +8 0 obj << /BaseFont /Helvetica /Encoding /WinAnsiEncoding @@ -141,7 +136,7 @@ endobj endobj %% Original object ID: 5 0 -10 0 obj +9 0 obj [ /PDF /Text @@ -149,24 +144,23 @@ endobj endobj xref -0 11 +0 10 0000000000 65535 f 0000000052 00000 n 0000000133 00000 n -0000000756 00000 n -0000000855 00000 n -0000000903 00000 n -0000000964 00000 n -0000001207 00000 n -0000001324 00000 n -0000001370 00000 n -0000001515 00000 n +0000000755 00000 n +0000000854 00000 n +0000000915 00000 n +0000001157 00000 n +0000001274 00000 n +0000001320 00000 n +0000001465 00000 n trailer << /QTest 2 0 R /Root 1 0 R - /Size 11 + /Size 10 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >> startxref -1551 +1500 %%EOF