Commit 96767fb104589ee1152152edc803b5f979a8390f
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.
Showing
4 changed files
with
17 additions
and
16 deletions
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 | 2020-10-27 Jay Berkenbilt <ejb@ql.org> | 8 | 2020-10-27 Jay Berkenbilt <ejb@ql.org> |
| 2 | 9 | ||
| 3 | * 10.0.2: release | 10 | * 10.0.2: release |
libqpdf/QPDF.cc
| @@ -2317,8 +2317,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, | @@ -2317,8 +2317,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, | ||
| 2317 | if (foreign.isReserved()) | 2317 | if (foreign.isReserved()) |
| 2318 | { | 2318 | { |
| 2319 | throw std::logic_error( | 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 | if (foreign.isPagesObject()) | 2323 | if (foreign.isPagesObject()) |
| @@ -2491,16 +2490,6 @@ QPDF::replaceForeignIndirectObjects( | @@ -2491,16 +2490,6 @@ QPDF::replaceForeignIndirectObjects( | ||
| 2491 | } | 2490 | } |
| 2492 | PointerHolder<Buffer> stream_buffer = | 2491 | PointerHolder<Buffer> stream_buffer = |
| 2493 | stream->getStreamDataBuffer(); | 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 | if ((foreign_stream_qpdf->m->immediate_copy_from) && | 2493 | if ((foreign_stream_qpdf->m->immediate_copy_from) && |
| 2505 | (stream_buffer.getPointer() == 0)) | 2494 | (stream_buffer.getPointer() == 0)) |
| 2506 | { | 2495 | { |
| @@ -2510,7 +2499,8 @@ QPDF::replaceForeignIndirectObjects( | @@ -2510,7 +2499,8 @@ QPDF::replaceForeignIndirectObjects( | ||
| 2510 | // have to keep duplicating the memory. | 2499 | // have to keep duplicating the memory. |
| 2511 | QTC::TC("qpdf", "QPDF immediate copy stream data"); | 2500 | QTC::TC("qpdf", "QPDF immediate copy stream data"); |
| 2512 | foreign.replaceStreamData(foreign.getRawStreamData(), | 2501 | foreign.replaceStreamData(foreign.getRawStreamData(), |
| 2513 | - filter, decode_parms); | 2502 | + old_dict.getKey("/Filter"), |
| 2503 | + old_dict.getKey("/DecodeParms")); | ||
| 2514 | stream_buffer = stream->getStreamDataBuffer(); | 2504 | stream_buffer = stream->getStreamDataBuffer(); |
| 2515 | } | 2505 | } |
| 2516 | PointerHolder<QPDFObjectHandle::StreamDataProvider> stream_provider = | 2506 | PointerHolder<QPDFObjectHandle::StreamDataProvider> stream_provider = |
| @@ -2518,7 +2508,9 @@ QPDF::replaceForeignIndirectObjects( | @@ -2518,7 +2508,9 @@ QPDF::replaceForeignIndirectObjects( | ||
| 2518 | if (stream_buffer.getPointer()) | 2508 | if (stream_buffer.getPointer()) |
| 2519 | { | 2509 | { |
| 2520 | QTC::TC("qpdf", "QPDF copy foreign stream with buffer"); | 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 | else if (stream_provider.getPointer()) | 2515 | else if (stream_provider.getPointer()) |
| 2524 | { | 2516 | { |
| @@ -2527,7 +2519,8 @@ QPDF::replaceForeignIndirectObjects( | @@ -2527,7 +2519,8 @@ QPDF::replaceForeignIndirectObjects( | ||
| 2527 | this->m->copied_stream_data_provider->registerForeignStream( | 2519 | this->m->copied_stream_data_provider->registerForeignStream( |
| 2528 | local_og, foreign); | 2520 | local_og, foreign); |
| 2529 | result.replaceStreamData(this->m->copied_streams, | 2521 | result.replaceStreamData(this->m->copied_streams, |
| 2530 | - filter, decode_parms); | 2522 | + dict.getKey("/Filter"), |
| 2523 | + dict.getKey("/DecodeParms")); | ||
| 2531 | } | 2524 | } |
| 2532 | else | 2525 | else |
| 2533 | { | 2526 | { |
| @@ -2545,7 +2538,8 @@ QPDF::replaceForeignIndirectObjects( | @@ -2545,7 +2538,8 @@ QPDF::replaceForeignIndirectObjects( | ||
| 2545 | this->m->copied_stream_data_provider->registerForeignStream( | 2538 | this->m->copied_stream_data_provider->registerForeignStream( |
| 2546 | local_og, foreign_stream_data); | 2539 | local_og, foreign_stream_data); |
| 2547 | result.replaceStreamData(this->m->copied_streams, | 2540 | result.replaceStreamData(this->m->copied_streams, |
| 2548 | - filter, decode_parms); | 2541 | + dict.getKey("/Filter"), |
| 2542 | + dict.getKey("/DecodeParms")); | ||
| 2549 | } | 2543 | } |
| 2550 | } | 2544 | } |
| 2551 | else | 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