Improve message for stream decoding error

Tweak the message so that we inform the user that we are mitigating
data loss.
This commit is contained in:
Jay Berkenbilt 2017-09-12 15:48:08 -04:00
parent eaacf94005
commit d31a7b76e7
16 changed files with 59 additions and 16 deletions

View File

@ -1,5 +1,10 @@
2017-09-12 Jay Berkenbilt <ejb@ql.org>
* Improve the error message that is issued when QPDFWriter
encounters a stream that can't be decoded. In particular, mention
that the stream will be copied without filtering to avoid data
loss.
* Add new methods to the C API to correspond to new additions to
QPDFWriter:
- qpdf_set_compress_streams

4
TODO
View File

@ -3,10 +3,6 @@ Before final 7.0.0
* Create release notes
* See if the error message that gets generated when retrying a stream
without filtering after error detection can be less scary.
Communicate that the original stream data is being preserved.
Soon
====

View File

@ -554,11 +554,13 @@ class QPDF
static bool pipeStreamData(QPDF* qpdf, int objid, int generation,
qpdf_offset_t offset, size_t length,
QPDFObjectHandle dict,
Pipeline* pipeline, bool suppress_warnings)
Pipeline* pipeline,
bool suppress_warnings,
bool will_retry)
{
return qpdf->pipeStreamData(
objid, generation, offset, length, dict, pipeline,
suppress_warnings);
suppress_warnings, will_retry);
}
};
friend class Pipe;
@ -688,7 +690,8 @@ class QPDF
qpdf_offset_t offset, size_t length,
QPDFObjectHandle dict,
Pipeline* pipeline,
bool suppress_warnings);
bool suppress_warnings,
bool will_retry);
// For QPDFWriter:

View File

@ -420,12 +420,21 @@ class QPDFObjectHandle
// configured filters. QPDFWriter handles this by attempting to
// get the stream data without filtering, but callers should
// consider a false return value when decode_level is not
// qpdf_dl_none to be a potential loss of data.
// qpdf_dl_none to be a potential loss of data. If you intend to
// retry in that case, pass true as the value of will_retry. This
// changes the warning issued by the library to indicate that the
// operation will be retried without filtering to avoid data loss.
QPDF_DLL
bool pipeStreamData(Pipeline*,
unsigned long encode_flags,
qpdf_stream_decode_level_e decode_level,
bool suppress_warnings = false);
QPDF_DLL
bool pipeStreamData(Pipeline*,
unsigned long encode_flags,
qpdf_stream_decode_level_e decode_level,
bool suppress_warnings,
bool will_retry);
// Legacy pipeStreamData. This maps to the the flags-based
// pipeStreamData as follows:

View File

@ -2382,7 +2382,8 @@ QPDF::pipeStreamData(int objid, int generation,
qpdf_offset_t offset, size_t length,
QPDFObjectHandle stream_dict,
Pipeline* pipeline,
bool suppress_warnings)
bool suppress_warnings,
bool will_retry)
{
bool success = false;
std::vector<PointerHolder<Pipeline> > to_delete;
@ -2430,6 +2431,13 @@ QPDF::pipeStreamData(int objid, int generation,
"error decoding stream data for object " +
QUtil::int_to_string(objid) + " " +
QUtil::int_to_string(generation) + ": " + e.what()));
if (will_retry)
{
warn(QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(),
"", this->m->file->getLastOffset(),
"stream will be re-processed without"
" filtering to avoid data loss"));
}
}
}
if (! success)

View File

@ -500,10 +500,20 @@ QPDFObjectHandle::pipeStreamData(Pipeline* p,
unsigned long encode_flags,
qpdf_stream_decode_level_e decode_level,
bool suppress_warnings)
{
return pipeStreamData(
p, encode_flags, decode_level, suppress_warnings, false);
}
bool
QPDFObjectHandle::pipeStreamData(Pipeline* p,
unsigned long encode_flags,
qpdf_stream_decode_level_e decode_level,
bool suppress_warnings, bool will_retry)
{
assertStream();
return dynamic_cast<QPDF_Stream*>(obj.getPointer())->pipeStreamData(
p, encode_flags, decode_level, suppress_warnings);
p, encode_flags, decode_level, suppress_warnings, will_retry);
}
bool

View File

@ -1623,7 +1623,7 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level,
((filter && compress) ? qpdf_ef_compress : 0)),
(filter
? (uncompress ? qpdf_dl_all : this->m->stream_decode_level)
: qpdf_dl_none));
: qpdf_dl_none), false, (attempt == 1));
popPipelineStack(&stream_data);
if (filter && (! filtered))
{

View File

@ -94,7 +94,7 @@ PointerHolder<Buffer>
QPDF_Stream::getStreamData(qpdf_stream_decode_level_e decode_level)
{
Pl_Buffer buf("stream data buffer");
if (! pipeStreamData(&buf, 0, decode_level, false))
if (! pipeStreamData(&buf, 0, decode_level, false, false))
{
throw std::logic_error("getStreamData called on unfilterable stream");
}
@ -106,7 +106,7 @@ PointerHolder<Buffer>
QPDF_Stream::getRawStreamData()
{
Pl_Buffer buf("stream data buffer");
pipeStreamData(&buf, 0, qpdf_dl_none, false);
pipeStreamData(&buf, 0, qpdf_dl_none, false, false);
QTC::TC("qpdf", "QPDF_Stream getRawStreamData");
return buf.getBuffer();
}
@ -373,7 +373,7 @@ bool
QPDF_Stream::pipeStreamData(Pipeline* pipeline,
unsigned long encode_flags,
qpdf_stream_decode_level_e decode_level,
bool suppress_warnings)
bool suppress_warnings, bool will_retry)
{
std::vector<std::string> filters;
int predictor = 1;
@ -540,7 +540,8 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline,
if (! QPDF::Pipe::pipeStreamData(this->qpdf, this->objid, this->generation,
this->offset, this->length,
this->stream_dict, pipeline,
suppress_warnings))
suppress_warnings,
will_retry))
{
filter = false;
}

View File

@ -25,7 +25,7 @@ class QPDF_Stream: public QPDFObject
bool pipeStreamData(Pipeline*,
unsigned long encode_flags,
qpdf_stream_decode_level_e decode_level,
bool suppress_warnings);
bool suppress_warnings, bool will_retry);
PointerHolder<Buffer> getStreamData(qpdf_stream_decode_level_e);
PointerHolder<Buffer> getRawStreamData();
void replaceStreamData(PointerHolder<Buffer> data,

View File

@ -1,2 +1,3 @@
WARNING: bad-data.pdf (file position 319): error decoding stream data for object 4 0: LZWDecoder: bad code received
WARNING: bad-data.pdf (file position 319): stream will be re-processed without filtering to avoid data loss
qpdf: operation succeeded with warnings; resulting file may have some problems

View File

@ -3,3 +3,4 @@ PDF Version: 1.3
File is not encrypted
File is not linearized
WARNING: bad-jpeg.pdf (file position 735): error decoding stream data for object 6 0: Not a JPEG file: starts with 0x77 0x77
WARNING: bad-jpeg.pdf (file position 735): stream will be re-processed without filtering to avoid data loss

View File

@ -1,2 +1,3 @@
WARNING: bad-jpeg.pdf (file position 735): error decoding stream data for object 6 0: Not a JPEG file: starts with 0x77 0x77
WARNING: bad-jpeg.pdf (file position 735): stream will be re-processed without filtering to avoid data loss
qpdf: operation succeeded with warnings; resulting file may have some problems

View File

@ -3,3 +3,8 @@ warning: damaged-stream.pdf (file position 426): error decoding stream data for
file: damaged-stream.pdf
pos : 426
text: error decoding stream data for object 5 0: LZWDecoder: bad code received
warning: damaged-stream.pdf (file position 426): stream will be re-processed without filtering to avoid data loss
code: 5
file: damaged-stream.pdf
pos : 426
text: stream will be re-processed without filtering to avoid data loss

View File

@ -3,3 +3,4 @@ PDF Version: 1.3
File is not encrypted
File is not linearized
WARNING: damaged-stream.pdf (file position 426): error decoding stream data for object 5 0: LZWDecoder: bad code received
WARNING: damaged-stream.pdf (file position 426): stream will be re-processed without filtering to avoid data loss

View File

@ -2,4 +2,5 @@ WARNING: issue-106.pdf: file is damaged
WARNING: issue-106.pdf (file position 809): xref not found
WARNING: issue-106.pdf: Attempting to reconstruct cross-reference table
WARNING: issue-106.pdf (file position 965): error decoding stream data for object 8 0: stream inflate: inflate: data: incorrect data check
WARNING: issue-106.pdf (file position 965): stream will be re-processed without filtering to avoid data loss
qpdf: operation succeeded with warnings; resulting file may have some problems

View File

@ -3,6 +3,7 @@ PDF Version: 1.3
File is not encrypted
File is not linearized
WARNING: split-content-stream-errors.pdf (file position 557): error decoding stream data for object 6 0: LZWDecoder: bad code received
WARNING: split-content-stream-errors.pdf (file position 557): stream will be re-processed without filtering to avoid data loss
WARNING: content stream: ignoring non-stream while parsing content streams
WARNING: split-content-stream-errors.pdf (file position 557): error decoding stream data for object 6 0: LZWDecoder: bad code received
WARNING: content stream (content stream object 6 0): errors while decoding content stream