Fix foreign stream copying bug (fixes #478)

This reverts an incorrect fix to #449 and codes it properly. The real
problem was that we were looking at the local dictionaries rather than
the foreign dictionaries when saving the foreign stream data. In the
case of direct objects, these happened to be the same, but in the case
of indirect objects, the object references could be pointing anywhere
since object numbers don't match up between the old and new files.
This commit is contained in:
Jay Berkenbilt 2020-10-31 11:43:31 -04:00
parent f1ae55a430
commit 96767fb104
4 changed files with 17 additions and 16 deletions

View File

@ -1,3 +1,10 @@
2020-10-31 Jay Berkenbilt <ejb@ql.org>
* My previous fix to #449 (handling foreign streams with indirect
objects in /Filter and/or /DecodeParms) was incorrect and caused
other problems. There is a now a correct fix to the original
problem. Fixes #478.
2020-10-27 Jay Berkenbilt <ejb@ql.org>
* 10.0.2: release

View File

@ -2317,8 +2317,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier,
if (foreign.isReserved())
{
throw std::logic_error(
"QPDF: attempting to copy a foreign reserved object: " +
QUtil::int_to_string(foreign.getObjectID()));
"QPDF: attempting to copy a foreign reserved object");
}
if (foreign.isPagesObject())
@ -2491,16 +2490,6 @@ QPDF::replaceForeignIndirectObjects(
}
PointerHolder<Buffer> 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))
{
@ -2510,7 +2499,8 @@ QPDF::replaceForeignIndirectObjects(
// have to keep duplicating the memory.
QTC::TC("qpdf", "QPDF immediate copy stream data");
foreign.replaceStreamData(foreign.getRawStreamData(),
filter, decode_parms);
old_dict.getKey("/Filter"),
old_dict.getKey("/DecodeParms"));
stream_buffer = stream->getStreamDataBuffer();
}
PointerHolder<QPDFObjectHandle::StreamDataProvider> stream_provider =
@ -2518,7 +2508,9 @@ QPDF::replaceForeignIndirectObjects(
if (stream_buffer.getPointer())
{
QTC::TC("qpdf", "QPDF copy foreign stream with buffer");
result.replaceStreamData(stream_buffer, filter, decode_parms);
result.replaceStreamData(stream_buffer,
dict.getKey("/Filter"),
dict.getKey("/DecodeParms"));
}
else if (stream_provider.getPointer())
{
@ -2527,7 +2519,8 @@ QPDF::replaceForeignIndirectObjects(
this->m->copied_stream_data_provider->registerForeignStream(
local_og, foreign);
result.replaceStreamData(this->m->copied_streams,
filter, decode_parms);
dict.getKey("/Filter"),
dict.getKey("/DecodeParms"));
}
else
{
@ -2545,7 +2538,8 @@ QPDF::replaceForeignIndirectObjects(
this->m->copied_stream_data_provider->registerForeignStream(
local_og, foreign_stream_data);
result.replaceStreamData(this->m->copied_streams,
filter, decode_parms);
dict.getKey("/Filter"),
dict.getKey("/DecodeParms"));
}
}
else