Commit 96767fb104589ee1152152edc803b5f979a8390f

Authored by Jay Berkenbilt
1 parent f1ae55a4

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.
ChangeLog
  1 +2020-10-31 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * My previous fix to #449 (handling foreign streams with indirect
  4 + objects in /Filter and/or /DecodeParms) was incorrect and caused
  5 + other problems. There is a now a correct fix to the original
  6 + problem. Fixes #478.
  7 +
1 8 2020-10-27 Jay Berkenbilt <ejb@ql.org>
2 9  
3 10 * 10.0.2: release
... ...
libqpdf/QPDF.cc
... ... @@ -2317,8 +2317,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier&amp; obj_copier,
2317 2317 if (foreign.isReserved())
2318 2318 {
2319 2319 throw std::logic_error(
2320   - "QPDF: attempting to copy a foreign reserved object: " +
2321   - QUtil::int_to_string(foreign.getObjectID()));
  2320 + "QPDF: attempting to copy a foreign reserved object");
2322 2321 }
2323 2322  
2324 2323 if (foreign.isPagesObject())
... ... @@ -2491,16 +2490,6 @@ QPDF::replaceForeignIndirectObjects(
2491 2490 }
2492 2491 PointerHolder<Buffer> stream_buffer =
2493 2492 stream->getStreamDataBuffer();
2494   - // Note: at this stage, dictionary keys may still be reserved.
2495   - // We have to handle that explicitly if we access anything.
2496   - auto get_as_direct = [&old_dict] (std::string const& key) {
2497   - QPDFObjectHandle obj = old_dict.getKey(key);
2498   - obj.makeDirect();
2499   - return obj;
2500   - };
2501   -
2502   - QPDFObjectHandle filter = get_as_direct("/Filter");
2503   - QPDFObjectHandle decode_parms = get_as_direct("/DecodeParms");
2504 2493 if ((foreign_stream_qpdf->m->immediate_copy_from) &&
2505 2494 (stream_buffer.getPointer() == 0))
2506 2495 {
... ... @@ -2510,7 +2499,8 @@ QPDF::replaceForeignIndirectObjects(
2510 2499 // have to keep duplicating the memory.
2511 2500 QTC::TC("qpdf", "QPDF immediate copy stream data");
2512 2501 foreign.replaceStreamData(foreign.getRawStreamData(),
2513   - filter, decode_parms);
  2502 + old_dict.getKey("/Filter"),
  2503 + old_dict.getKey("/DecodeParms"));
2514 2504 stream_buffer = stream->getStreamDataBuffer();
2515 2505 }
2516 2506 PointerHolder<QPDFObjectHandle::StreamDataProvider> stream_provider =
... ... @@ -2518,7 +2508,9 @@ QPDF::replaceForeignIndirectObjects(
2518 2508 if (stream_buffer.getPointer())
2519 2509 {
2520 2510 QTC::TC("qpdf", "QPDF copy foreign stream with buffer");
2521   - result.replaceStreamData(stream_buffer, filter, decode_parms);
  2511 + result.replaceStreamData(stream_buffer,
  2512 + dict.getKey("/Filter"),
  2513 + dict.getKey("/DecodeParms"));
2522 2514 }
2523 2515 else if (stream_provider.getPointer())
2524 2516 {
... ... @@ -2527,7 +2519,8 @@ QPDF::replaceForeignIndirectObjects(
2527 2519 this->m->copied_stream_data_provider->registerForeignStream(
2528 2520 local_og, foreign);
2529 2521 result.replaceStreamData(this->m->copied_streams,
2530   - filter, decode_parms);
  2522 + dict.getKey("/Filter"),
  2523 + dict.getKey("/DecodeParms"));
2531 2524 }
2532 2525 else
2533 2526 {
... ... @@ -2545,7 +2538,8 @@ QPDF::replaceForeignIndirectObjects(
2545 2538 this->m->copied_stream_data_provider->registerForeignStream(
2546 2539 local_og, foreign_stream_data);
2547 2540 result.replaceStreamData(this->m->copied_streams,
2548   - filter, decode_parms);
  2541 + dict.getKey("/Filter"),
  2542 + dict.getKey("/DecodeParms"));
2549 2543 }
2550 2544 }
2551 2545 else
... ...
qpdf/qtest/qpdf/indirect-filter-out-0.pdf
No preview for this file type
qpdf/qtest/qpdf/indirect-filter-out-1.pdf
No preview for this file type