aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2017-07-29 16:40:31 +0200
committerJay Berkenbilt <ejb@ql.org>2017-07-29 18:19:04 +0200
commitb389268f16fcd571bbc57ef848caba25490a1b86 (patch)
tree97261a0794699745ce9329265761fb70a0b1ec24 /libqpdf
parenta136824243e5aa8691a9b1f5fd5401ef7bef1a31 (diff)
downloadqpdf-b389268f16fcd571bbc57ef848caba25490a1b86.tar.zst
Better handle split content streams (fixes #73)
When parsing content streams, allow content to be split arbitrarily across stream boundaries.
Diffstat (limited to 'libqpdf')
-rw-r--r--libqpdf/QPDFObjectHandle.cc55
1 files changed, 41 insertions, 14 deletions
diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc
index bac233df..e263a3ec 100644
--- a/libqpdf/QPDFObjectHandle.cc
+++ b/libqpdf/QPDFObjectHandle.cc
@@ -13,6 +13,7 @@
#include <qpdf/QPDF_Dictionary.hh>
#include <qpdf/QPDF_Stream.hh>
#include <qpdf/QPDF_Reserved.hh>
+#include <qpdf/Pl_Buffer.hh>
#include <qpdf/BufferInputSource.hh>
#include <qpdf/QPDFExc.hh>
@@ -739,37 +740,63 @@ QPDFObjectHandle::parseContentStream(QPDFObjectHandle stream_or_array,
{
streams.push_back(stream_or_array);
}
+ Pl_Buffer buf("concatenated stream data buffer");
+ std::string all_description = "content stream objects";
+ bool first = true;
for (std::vector<QPDFObjectHandle>::iterator iter = streams.begin();
iter != streams.end(); ++iter)
{
QPDFObjectHandle stream = *iter;
if (! stream.isStream())
{
- throw std::logic_error(
- "QPDFObjectHandle: parseContentStream called on non-stream");
+ QTC::TC("qpdf", "QPDFObjectHandle non-stream in parsecontent");
+ warn(stream.getOwningQPDF(),
+ QPDFExc(qpdf_e_damaged_pdf, "content stream",
+ "", 0,
+ "ignoring non-stream while parsing content streams"));
}
- try
- {
- parseContentStream_internal(stream, callbacks);
- }
- catch (TerminateParsing&)
+ else
{
- return;
+ std::string og = QUtil::int_to_string(stream.getObjectID()) + " " +
+ QUtil::int_to_string(stream.getGeneration());
+ std::string description = "content stream object " + og;
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ all_description += ",";
+ }
+ all_description += " " + og;
+ if (! stream.pipeStreamData(&buf, true, false, false, false))
+ {
+ QTC::TC("qpdf", "QPDFObjectHandle errors in parsecontent");
+ warn(stream.getOwningQPDF(),
+ QPDFExc(qpdf_e_damaged_pdf, "content stream",
+ description, 0,
+ "errors while decoding content stream"));
+ }
}
}
+ PointerHolder<Buffer> stream_data = buf.getBuffer();
+ try
+ {
+ parseContentStream_internal(stream_data, all_description, callbacks);
+ }
+ catch (TerminateParsing&)
+ {
+ return;
+ }
callbacks->handleEOF();
}
void
-QPDFObjectHandle::parseContentStream_internal(QPDFObjectHandle stream,
+QPDFObjectHandle::parseContentStream_internal(PointerHolder<Buffer> stream_data,
+ std::string const& description,
ParserCallbacks* callbacks)
{
- stream.assertStream();
- PointerHolder<Buffer> stream_data = stream.getStreamData();
size_t length = stream_data->getSize();
- std::string description = "content stream object " +
- QUtil::int_to_string(stream.getObjectID()) + " " +
- QUtil::int_to_string(stream.getGeneration());
PointerHolder<InputSource> input =
new BufferInputSource(description, stream_data.getPointer());
QPDFTokenizer tokenizer;