2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-05-28 16:00:53 +00:00

Add new QPDF::warn that takes most of QPDFExc's arguments

This commit is contained in:
Jay Berkenbilt 2022-04-23 18:03:44 -04:00
parent 696ca53205
commit 68e721981a
13 changed files with 93 additions and 113 deletions

View File

@ -1,5 +1,10 @@
2022-04-23 Jay Berkenbilt <ejb@ql.org> 2022-04-23 Jay Berkenbilt <ejb@ql.org>
* Add a new QPDF::warn method that takes the parameters of
QPDFExc's constructor except for the filename, which is taken from
the QPDF object. This is a shorter way to issue warnings on behalf
of a QPDF object.
* Add new method QUtil::is_explicit_utf8 that tests whether a * Add new method QUtil::is_explicit_utf8 that tests whether a
string is explicitly marked as being UTF-8 encoded, as allowed by string is explicitly marked as being UTF-8 encoded, as allowed by
the PDF 2.0 spec. Such a string starts with the bytes 0xEF 0xBB the PDF 2.0 spec. Such a string starts with the bytes 0xEF 0xBB

2
TODO
View File

@ -21,8 +21,6 @@ Misc
--show-encryption could potentially retry with this option if the --show-encryption could potentially retry with this option if the
first time doesn't work. Then, with the file open, we can read the first time doesn't work. Then, with the file open, we can read the
encryption dictionary normally. encryption dictionary normally.
* Have a warn in QPDF that passes its variable arguments onto QPDFExc
so you don't have to do warn(QPDFExc(...))
* Find all places in the code that write to std::cout, std::err, * Find all places in the code that write to std::cout, std::err,
stdout, or stderr to make sure they obey default output stream stdout, or stderr to make sure they obey default output stream
settings for QPDF and QPDFJob. This probably includes adding a settings for QPDF and QPDFJob. This probably includes adding a

View File

@ -262,6 +262,16 @@ class QPDF
// rules, and it will be available with getWarnings(). // rules, and it will be available with getWarnings().
QPDF_DLL QPDF_DLL
void warn(QPDFExc const& e); void warn(QPDFExc const& e);
// Same as above but creates the QPDFExc object using the
// arguments passed to warn. The filename argument to QPDFExc is
// omitted. This method uses the filename associated with the QPDF
// object.
QPDF_DLL
void warn(
qpdf_error_code_e error_code,
std::string const& object,
qpdf_offset_t offset,
std::string const& message);
QPDF_DLL QPDF_DLL
std::string getFilename() const; std::string getFilename() const;

View File

@ -18,14 +18,7 @@ get_description(QPDFObjectHandle& node)
static void static void
warn(QPDF& qpdf, QPDFObjectHandle& node, std::string const& msg) warn(QPDF& qpdf, QPDFObjectHandle& node, std::string const& msg)
{ {
qpdf.warn( qpdf.warn(qpdf_e_damaged_pdf, get_description(node), 0, msg);
// line-break
QPDFExc(
qpdf_e_damaged_pdf,
qpdf.getFilename(),
get_description(node),
0,
msg));
} }
static void static void

View File

@ -459,12 +459,7 @@ QPDF::parse(char const* password)
PatternFinder hf(*this, &QPDF::findHeader); PatternFinder hf(*this, &QPDF::findHeader);
if (!this->m->file->findFirst("%PDF-", 0, 1024, hf)) { if (!this->m->file->findFirst("%PDF-", 0, 1024, hf)) {
QTC::TC("qpdf", "QPDF not a pdf file"); QTC::TC("qpdf", "QPDF not a pdf file");
warn(QPDFExc( warn(qpdf_e_damaged_pdf, "", 0, "can't find PDF header");
qpdf_e_damaged_pdf,
this->m->file->getName(),
"",
0,
"can't find PDF header"));
// QPDFWriter writes files that usually require at least // QPDFWriter writes files that usually require at least
// version 1.2 for /FlateDecode // version 1.2 for /FlateDecode
this->m->pdf_version = "1.2"; this->m->pdf_version = "1.2";
@ -541,6 +536,16 @@ QPDF::warn(QPDFExc const& e)
} }
} }
void
QPDF::warn(
qpdf_error_code_e error_code,
std::string const& object,
qpdf_offset_t offset,
std::string const& message)
{
warn(QPDFExc(error_code, this->getFilename(), object, offset, message));
}
void void
QPDF::setTrailer(QPDFObjectHandle obj) QPDF::setTrailer(QPDFObjectHandle obj)
{ {
@ -562,19 +567,13 @@ QPDF::reconstruct_xref(QPDFExc& e)
this->m->reconstructed_xref = true; this->m->reconstructed_xref = true;
warn(QPDFExc( warn(qpdf_e_damaged_pdf, "", 0, "file is damaged");
qpdf_e_damaged_pdf,
this->m->file->getName(),
"",
0,
"file is damaged"));
warn(e); warn(e);
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
"", "",
0, 0,
"Attempting to reconstruct cross-reference table")); "Attempting to reconstruct cross-reference table");
// Delete all references to type 1 (uncompressed) objects // Delete all references to type 1 (uncompressed) objects
std::set<QPDFObjGen> to_delete; std::set<QPDFObjGen> to_delete;
@ -700,12 +699,11 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) { if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) {
if (skipped_space) { if (skipped_space) {
QTC::TC("qpdf", "QPDF xref skipped space"); QTC::TC("qpdf", "QPDF xref skipped space");
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
"", "",
0, 0,
"extraneous whitespace seen before xref")); "extraneous whitespace seen before xref");
} }
QTC::TC( QTC::TC(
"qpdf", "qpdf",
@ -753,15 +751,14 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
} }
if ((size < 1) || (size - 1 != max_obj)) { if ((size < 1) || (size - 1 != max_obj)) {
QTC::TC("qpdf", "QPDF xref size mismatch"); QTC::TC("qpdf", "QPDF xref size mismatch");
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
"", "",
0, 0,
(std::string("reported number of objects (") + (std::string("reported number of objects (") +
QUtil::int_to_string(size) + QUtil::int_to_string(size) +
") is not one plus the highest object number (" + ") is not one plus the highest object number (" +
QUtil::int_to_string(max_obj) + ")"))); QUtil::int_to_string(max_obj) + ")"));
} }
// We no longer need the deleted_objects table, so go ahead and // We no longer need the deleted_objects table, so go ahead and
@ -885,12 +882,11 @@ QPDF::parse_xrefEntry(
} }
if (invalid) { if (invalid) {
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
"xref table", "xref table",
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
"accepting invalid xref table entry")); "accepting invalid xref table entry");
} }
f1 = QUtil::string_to_ll(f1_str.c_str()); f1 = QUtil::string_to_ll(f1_str.c_str());
@ -1813,12 +1809,11 @@ QPDF::readObjectAtOffset(
// ignore these. // ignore these.
if (offset == 0) { if (offset == 0) {
QTC::TC("qpdf", "QPDF bogus 0 offset", 0); QTC::TC("qpdf", "QPDF bogus 0 offset", 0);
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
this->m->last_object_description, this->m->last_object_description,
0, 0,
"object has offset 0")); "object has offset 0");
return QPDFObjectHandle::newNull(); return QPDFObjectHandle::newNull();
} }
@ -1898,16 +1893,15 @@ QPDF::readObjectAtOffset(
return result; return result;
} else { } else {
QTC::TC("qpdf", "QPDF object gone after xref reconstruction"); QTC::TC("qpdf", "QPDF object gone after xref reconstruction");
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
"", "",
0, 0,
std::string( std::string(
"object " + QUtil::int_to_string(exp_objid) + " " + "object " + QUtil::int_to_string(exp_objid) + " " +
QUtil::int_to_string(exp_generation) + QUtil::int_to_string(exp_generation) +
" not found in file after regenerating" " not found in file after regenerating"
" cross reference table"))); " cross reference table"));
return QPDFObjectHandle::newNull(); return QPDFObjectHandle::newNull();
} }
} else { } else {
@ -1921,12 +1915,11 @@ QPDF::readObjectAtOffset(
if (!(readToken(this->m->file) == if (!(readToken(this->m->file) ==
QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) { QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) {
QTC::TC("qpdf", "QPDF err expected endobj"); QTC::TC("qpdf", "QPDF err expected endobj");
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
this->m->last_object_description, this->m->last_object_description,
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
"expected endobj")); "expected endobj");
} }
QPDFObjGen og(objid, generation); QPDFObjGen og(objid, generation);
@ -2005,13 +1998,12 @@ QPDF::resolve(int objid, int generation)
// indirectly in some key that has to be resolved during // indirectly in some key that has to be resolved during
// object parsing, such as stream length. // object parsing, such as stream length.
QTC::TC("qpdf", "QPDF recursion loop in resolve"); QTC::TC("qpdf", "QPDF recursion loop in resolve");
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
"", "",
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
("loop detected resolving object " + QUtil::int_to_string(objid) + ("loop detected resolving object " + QUtil::int_to_string(objid) +
" " + QUtil::int_to_string(generation)))); " " + QUtil::int_to_string(generation)));
return std::shared_ptr<QPDFObject>(new QPDF_Null); return std::shared_ptr<QPDFObject>(new QPDF_Null);
} }
ResolveRecorder rr(this, og); ResolveRecorder rr(this, og);
@ -2054,14 +2046,13 @@ QPDF::resolve(int objid, int generation)
} catch (QPDFExc& e) { } catch (QPDFExc& e) {
warn(e); warn(e);
} catch (std::exception& e) { } catch (std::exception& e) {
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
"", "",
0, 0,
("object " + QUtil::int_to_string(objid) + "/" + ("object " + QUtil::int_to_string(objid) + "/" +
QUtil::int_to_string(generation) + QUtil::int_to_string(generation) +
": error reading object: " + e.what()))); ": error reading object: " + e.what()));
} }
} }
if (this->m->obj_cache.count(og) == 0) { if (this->m->obj_cache.count(og) == 0) {
@ -2112,13 +2103,12 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
QPDFObjectHandle dict = obj_stream.getDict(); QPDFObjectHandle dict = obj_stream.getDict();
if (!dict.isDictionaryOfType("/ObjStm")) { if (!dict.isDictionaryOfType("/ObjStm")) {
QTC::TC("qpdf", "QPDF ERR object stream with wrong type"); QTC::TC("qpdf", "QPDF ERR object stream with wrong type");
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
this->m->last_object_description, this->m->last_object_description,
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
("supposed object stream " + ("supposed object stream " +
QUtil::int_to_string(obj_stream_number) + " has wrong type"))); QUtil::int_to_string(obj_stream_number) + " has wrong type"));
} }
if (!(dict.getKey("/N").isInteger() && dict.getKey("/First").isInteger())) { if (!(dict.getKey("/N").isInteger() && dict.getKey("/First").isInteger())) {

View File

@ -2677,14 +2677,13 @@ QPDFJob::handlePageSpecs(
*other_afdh, *other_afdh,
&referenced_fields); &referenced_fields);
} catch (std::exception& e) { } catch (std::exception& e) {
pdf.warn(QPDFExc( pdf.warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
pdf.getFilename(),
"", "",
0, 0,
("Exception caught while fixing copied" ("Exception caught while fixing copied"
" annotations. This may be a qpdf bug. " + " annotations. This may be a qpdf bug. " +
std::string("Exception: ") + e.what()))); std::string("Exception: ") + e.what()));
} }
} }
} }
@ -3127,14 +3126,13 @@ QPDFJob::doSplitPages(QPDF& pdf, bool& warnings)
try { try {
out_afdh->fixCopiedAnnotations(new_page, page, afdh); out_afdh->fixCopiedAnnotations(new_page, page, afdh);
} catch (std::exception& e) { } catch (std::exception& e) {
pdf.warn(QPDFExc( pdf.warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
pdf.getFilename(),
"", "",
0, 0,
"Exception caught while fixing copied" ("Exception caught while fixing copied"
" annotations. This may be a qpdf bug." + " annotations. This may be a qpdf bug." +
std::string("Exception: ") + e.what())); std::string("Exception: ") + e.what()));
} }
} }
} }

View File

@ -1556,8 +1556,9 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
item.getOwningQPDF(), item.getOwningQPDF(),
QPDFExc( QPDFExc(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
description, "",
"item index " + QUtil::int_to_string(i) + " (from 0)", description + ": item index " +
QUtil::int_to_string(i) + " (from 0)",
0, 0,
"ignoring non-stream in an array of streams")); "ignoring non-stream in an array of streams"));
} }

View File

@ -302,12 +302,10 @@ QPDF_Stream::filterable(
if (!filters_okay) { if (!filters_okay) {
QTC::TC("qpdf", "QPDF_Stream invalid filter"); QTC::TC("qpdf", "QPDF_Stream invalid filter");
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
qpdf->getFilename(),
"",
this->offset, this->offset,
"stream filter type is not name or array")); "stream filter type is not name or array");
return false; return false;
} }
@ -355,13 +353,11 @@ QPDF_Stream::filterable(
// one case of a file whose /DecodeParms was [ << >> ] when // one case of a file whose /DecodeParms was [ << >> ] when
// /Filters was empty has been seen in the wild. // /Filters was empty has been seen in the wild.
if ((filters.size() != 0) && (decode_parms.size() != filters.size())) { if ((filters.size() != 0) && (decode_parms.size() != filters.size())) {
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
qpdf->getFilename(),
"",
this->offset, this->offset,
"stream /DecodeParms length is" "stream /DecodeParms length is"
" inconsistent with filters")); " inconsistent with filters");
filterable = false; filterable = false;
} }
@ -474,12 +470,7 @@ QPDF_Stream::pipeStreamData(
Pl_Flate* flate = dynamic_cast<Pl_Flate*>(pipeline); Pl_Flate* flate = dynamic_cast<Pl_Flate*>(pipeline);
if (flate != nullptr) { if (flate != nullptr) {
flate->setWarnCallback([this](char const* msg, int code) { flate->setWarnCallback([this](char const* msg, int code) {
warn(QPDFExc( warn(qpdf_e_damaged_pdf, this->offset, msg);
qpdf_e_damaged_pdf,
qpdf->getFilename(),
"",
this->offset,
msg));
}); });
} }
} }
@ -551,34 +542,28 @@ QPDF_Stream::pipeStreamData(
if (filter && (!suppress_warnings) && normalizer.get() && if (filter && (!suppress_warnings) && normalizer.get() &&
normalizer->anyBadTokens()) { normalizer->anyBadTokens()) {
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
qpdf->getFilename(),
"",
this->offset, this->offset,
"content normalization encountered bad tokens")); "content normalization encountered bad tokens");
if (normalizer->lastTokenWasBad()) { if (normalizer->lastTokenWasBad()) {
QTC::TC("qpdf", "QPDF_Stream bad token at end during normalize"); QTC::TC("qpdf", "QPDF_Stream bad token at end during normalize");
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
qpdf->getFilename(),
"",
this->offset, this->offset,
"normalized content ended with a bad token;" "normalized content ended with a bad token;"
" you may be able to resolve this by" " you may be able to resolve this by"
" coalescing content streams in combination" " coalescing content streams in combination"
" with normalizing content. From the command" " with normalizing content. From the command"
" line, specify --coalesce-contents")); " line, specify --coalesce-contents");
} }
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
qpdf->getFilename(),
"",
this->offset, this->offset,
"Resulting stream data may be corrupted but is" "Resulting stream data may be corrupted but is"
" may still useful for manual inspection." " may still useful for manual inspection."
" For more information on this warning, search" " For more information on this warning, search"
" for content normalization in the manual.")); " for content normalization in the manual.");
} }
return success; return success;
@ -645,7 +630,10 @@ QPDF_Stream::replaceDict(QPDFObjectHandle new_dict)
} }
void void
QPDF_Stream::warn(QPDFExc const& e) QPDF_Stream::warn(
qpdf_error_code_e error_code,
qpdf_offset_t offset,
std::string const& message)
{ {
this->qpdf->warn(e); this->qpdf->warn(error_code, "", offset, message);
} }

View File

@ -803,12 +803,11 @@ QPDF::initializeEncryption()
// Treating a missing ID as the empty string enables qpdf to // Treating a missing ID as the empty string enables qpdf to
// decrypt some invalid encrypted files with no /ID that // decrypt some invalid encrypted files with no /ID that
// poppler can read but Adobe Reader can't. // poppler can read but Adobe Reader can't.
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
"trailer", "trailer",
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
"invalid /ID in trailer dictionary")); "invalid /ID in trailer dictionary");
} }
QPDFObjectHandle encryption_dict = this->m->trailer.getKey("/Encrypt"); QPDFObjectHandle encryption_dict = this->m->trailer.getKey("/Encrypt");
@ -831,13 +830,12 @@ QPDF::initializeEncryption()
"unsupported encryption filter"); "unsupported encryption filter");
} }
if (!encryption_dict.getKey("/SubFilter").isNull()) { if (!encryption_dict.getKey("/SubFilter").isNull()) {
warn(QPDFExc( warn(
qpdf_e_unsupported, qpdf_e_unsupported,
this->m->file->getName(),
"encryption dictionary", "encryption dictionary",
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
"file uses encryption SubFilters," "file uses encryption SubFilters,"
" which qpdf does not support")); " which qpdf does not support");
} }
if (!(encryption_dict.getKey("/V").isInteger() && if (!(encryption_dict.getKey("/V").isInteger() &&
@ -1067,13 +1065,12 @@ QPDF::initializeEncryption()
this->m->encp->encryption_key = recover_encryption_key_with_password( this->m->encp->encryption_key = recover_encryption_key_with_password(
this->m->encp->provided_password, data, perms_valid); this->m->encp->provided_password, data, perms_valid);
if (!perms_valid) { if (!perms_valid) {
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
"encryption dictionary", "encryption dictionary",
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
"/Perms field in encryption dictionary" "/Perms field in encryption dictionary"
" doesn't match expected value")); " doesn't match expected value");
} }
} }
} }
@ -1130,14 +1127,13 @@ QPDF::decryptString(std::string& str, int objid, int generation)
break; break;
default: default:
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
this->m->last_object_description, this->m->last_object_description,
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
"unknown encryption filter for strings" "unknown encryption filter for strings"
" (check /StrF in /Encrypt dictionary);" " (check /StrF in /Encrypt dictionary);"
" strings may be decrypted improperly")); " strings may be decrypted improperly");
// To avoid repeated warnings, reset cf_string. Assume // To avoid repeated warnings, reset cf_string. Assume
// we'd want to use AES if V == 4. // we'd want to use AES if V == 4.
this->m->encp->cf_string = e_aes; this->m->encp->cf_string = e_aes;

View File

@ -266,15 +266,14 @@ QPDF::pushInheritedAttributesToPageInternal(
"Pages object", "Pages object",
cur_pages.getObjectID(), cur_pages.getObjectID(),
cur_pages.getGeneration()); cur_pages.getGeneration());
warn(QPDFExc( warn(
qpdf_e_pages, qpdf_e_pages,
this->m->file->getName(),
this->m->last_object_description, this->m->last_object_description,
0, 0,
"Unknown key " + key + ("Unknown key " + key +
" in /Pages object" " in /Pages object"
" is being discarded as a result of" " is being discarded as a result of"
" flattening the /Pages tree")); " flattening the /Pages tree"));
} }
} }
} }

View File

@ -130,12 +130,11 @@ QPDF::getAllPagesInternal(
} }
if (!cur_node.isDictionaryOfType(wanted_type)) { if (!cur_node.isDictionaryOfType(wanted_type)) {
warn(QPDFExc( warn(
qpdf_e_damaged_pdf, qpdf_e_damaged_pdf,
this->m->file->getName(),
"page tree node", "page tree node",
this->m->file->getLastOffset(), this->m->file->getLastOffset(),
"/Type key should be " + wanted_type + " but is not; overriding")); "/Type key should be " + wanted_type + " but is not; overriding");
cur_node.replaceKey("/Type", QPDFObjectHandle::newName(wanted_type)); cur_node.replaceKey("/Type", QPDFObjectHandle::newName(wanted_type));
} }
visited.erase(this_og); visited.erase(this_og);

View File

@ -90,7 +90,10 @@ class QPDF_Stream: public QPDFObject
std::vector<std::shared_ptr<QPDFStreamFilter>>& filters, std::vector<std::shared_ptr<QPDFStreamFilter>>& filters,
bool& specialized_compression, bool& specialized_compression,
bool& lossy_compression); bool& lossy_compression);
void warn(QPDFExc const& e); void warn(
qpdf_error_code_e error_code,
qpdf_offset_t offset,
std::string const& message);
void setDictDescription(); void setDictDescription();
void setStreamDescription(); void setStreamDescription();

View File

@ -4,7 +4,7 @@ File is not encrypted
File is not linearized File is not linearized
WARNING: split-content-stream-errors.pdf (offset 557): error decoding stream data for object 6 0: LZWDecoder: bad code received WARNING: split-content-stream-errors.pdf (offset 557): error decoding stream data for object 6 0: LZWDecoder: bad code received
WARNING: split-content-stream-errors.pdf (offset 557): stream will be re-processed without filtering to avoid data loss WARNING: split-content-stream-errors.pdf (offset 557): stream will be re-processed without filtering to avoid data loss
WARNING: page object 3 0 (item index 0 (from 0)): ignoring non-stream in an array of streams WARNING: page object 3 0: item index 0 (from 0): ignoring non-stream in an array of streams
WARNING: split-content-stream-errors.pdf (offset 557): error decoding stream data for object 6 0: LZWDecoder: bad code received WARNING: split-content-stream-errors.pdf (offset 557): error decoding stream data for object 6 0: LZWDecoder: bad code received
ERROR: page 1: content stream (content stream object 6 0): errors while decoding content stream ERROR: page 1: content stream (content stream object 6 0): errors while decoding content stream
qpdf: errors detected qpdf: errors detected