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 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&amp; obj_copier, @@ -2317,8 +2317,7 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier&amp; 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