From 956c8f643219778c445d7062d1d0e7e3b96c7676 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Wed, 21 Oct 2020 18:50:29 -0400 Subject: Obscure bug fix copying foreign streams in special cases (fixes #449) Specifically, if a stream had its stream data replaced and had indirect /Filter or /DecodeParms, it would result in non-silent loss of data and/or internal error. --- libqpdf/QPDF.cc | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'libqpdf') diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 1cbef133..3b6d70ee 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -2313,7 +2313,8 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, if (foreign.isReserved()) { throw std::logic_error( - "QPDF: attempting to copy a foreign reserved object"); + "QPDF: attempting to copy a foreign reserved object: " + + QUtil::int_to_string(foreign.getObjectID())); } if (foreign.isPagesObject()) @@ -2486,6 +2487,16 @@ QPDF::replaceForeignIndirectObjects( } PointerHolder stream_buffer = stream->getStreamDataBuffer(); + // Note: at this stage, dictionary keys may still be reserved. + // We have to handle that explicitly if we access anything. + auto get_as_direct = [&old_dict] (std::string const& key) { + QPDFObjectHandle obj = old_dict.getKey(key); + obj.makeDirect(); + return obj; + }; + + QPDFObjectHandle filter = get_as_direct("/Filter"); + QPDFObjectHandle decode_parms = get_as_direct("/DecodeParms"); if ((foreign_stream_qpdf->m->immediate_copy_from) && (stream_buffer.getPointer() == 0)) { @@ -2495,8 +2506,7 @@ QPDF::replaceForeignIndirectObjects( // have to keep duplicating the memory. QTC::TC("qpdf", "QPDF immediate copy stream data"); foreign.replaceStreamData(foreign.getRawStreamData(), - dict.getKey("/Filter"), - dict.getKey("/DecodeParms")); + filter, decode_parms); stream_buffer = stream->getStreamDataBuffer(); } PointerHolder stream_provider = @@ -2504,9 +2514,7 @@ QPDF::replaceForeignIndirectObjects( if (stream_buffer.getPointer()) { QTC::TC("qpdf", "QPDF copy foreign stream with buffer"); - result.replaceStreamData(stream_buffer, - dict.getKey("/Filter"), - dict.getKey("/DecodeParms")); + result.replaceStreamData(stream_buffer, filter, decode_parms); } else if (stream_provider.getPointer()) { @@ -2515,8 +2523,7 @@ QPDF::replaceForeignIndirectObjects( this->m->copied_stream_data_provider->registerForeignStream( local_og, foreign); result.replaceStreamData(this->m->copied_streams, - dict.getKey("/Filter"), - dict.getKey("/DecodeParms")); + filter, decode_parms); } else { @@ -2534,8 +2541,7 @@ QPDF::replaceForeignIndirectObjects( this->m->copied_stream_data_provider->registerForeignStream( local_og, foreign_stream_data); result.replaceStreamData(this->m->copied_streams, - dict.getKey("/Filter"), - dict.getKey("/DecodeParms")); + filter, decode_parms); } } else -- cgit v1.2.3-54-g00ecf