aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDF.cc
diff options
context:
space:
mode:
authorm-holger <m-holger@kubitscheck.org>2023-07-08 13:17:48 +0200
committerm-holger <m-holger@kubitscheck.org>2023-07-08 17:31:57 +0200
commitaabd3f6f9b09e844958fd4ee07bde5e8df546fc4 (patch)
treee6ae09b7061a8c0481106a34956ec3997e645684 /libqpdf/QPDF.cc
parentef866d68cd77cad9640350715adf3374fd5719c7 (diff)
downloadqpdf-aabd3f6f9b09e844958fd4ee07bde5e8df546fc4.tar.zst
Add private method QPDF::validateStreamLineEnd
Diffstat (limited to 'libqpdf/QPDF.cc')
-rw-r--r--libqpdf/QPDF.cc84
1 files changed, 45 insertions, 39 deletions
diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc
index 3fbb4da1..05929764 100644
--- a/libqpdf/QPDF.cc
+++ b/libqpdf/QPDF.cc
@@ -1324,6 +1324,47 @@ QPDF::readObject(std::string const& description, QPDFObjGen og)
void
QPDF::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset)
{
+ validateStreamLineEnd(object, og, offset);
+
+ // Must get offset before accessing any additional objects since resolving a previously
+ // unresolved indirect object will change file position.
+ qpdf_offset_t stream_offset = m->file->tell();
+ size_t length = 0;
+
+ try {
+ auto length_obj = object.getKey("/Length");
+
+ if (!length_obj.isInteger()) {
+ if (length_obj.isNull()) {
+ QTC::TC("qpdf", "QPDF stream without length");
+ throw damagedPDF(offset, "stream dictionary lacks /Length key");
+ }
+ QTC::TC("qpdf", "QPDF stream length not integer");
+ throw damagedPDF(offset, "/Length key in stream dictionary is not an integer");
+ }
+
+ length = toS(length_obj.getUIntValue());
+ // Seek in two steps to avoid potential integer overflow
+ m->file->seek(stream_offset, SEEK_SET);
+ m->file->seek(toO(length), SEEK_CUR);
+ if (!readToken(m->file).isWord("endstream")) {
+ QTC::TC("qpdf", "QPDF missing endstream");
+ throw damagedPDF("expected endstream");
+ }
+ } catch (QPDFExc& e) {
+ if (m->attempt_recovery) {
+ warn(e);
+ length = recoverStreamLength(m->file, og, stream_offset);
+ } else {
+ throw;
+ }
+ }
+ object = newIndirect(og, QPDF_Stream::create(this, og, object, stream_offset, length));
+}
+
+void
+QPDF::validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset)
+{
// The PDF specification states that the word "stream" should be followed by either a carriage
// return and a newline or by a newline alone. It specifically disallowed following it by a
// carriage return alone since, in that case, there would be no way to tell whether the NL in a
@@ -1336,12 +1377,12 @@ QPDF::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset)
if (m->file->read(&ch, 1) == 0) {
// A premature EOF here will result in some other problem that will get reported at
// another time.
- break;
+ return;
}
if (ch == '\n') {
// ready to read stream data
QTC::TC("qpdf", "QPDF stream with NL only");
- break;
+ return;
}
if (ch == '\r') {
// Read another character
@@ -1358,52 +1399,17 @@ QPDF::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset)
m->file->tell(), "stream keyword followed by carriage return only"));
}
}
- break;
+ return;
}
if (!QUtil::is_space(ch)) {
QTC::TC("qpdf", "QPDF stream without newline");
m->file->unreadCh(ch);
warn(damagedPDF(
m->file->tell(), "stream keyword not followed by proper line terminator"));
- break;
+ return;
}
warn(damagedPDF(m->file->tell(), "stream keyword followed by extraneous whitespace"));
}
-
- // Must get offset before accessing any additional objects since resolving a previously
- // unresolved indirect object will change file position.
- qpdf_offset_t stream_offset = m->file->tell();
- size_t length = 0;
-
- try {
- auto length_obj = object.getKey("/Length");
-
- if (!length_obj.isInteger()) {
- if (length_obj.isNull()) {
- QTC::TC("qpdf", "QPDF stream without length");
- throw damagedPDF(offset, "stream dictionary lacks /Length key");
- }
- QTC::TC("qpdf", "QPDF stream length not integer");
- throw damagedPDF(offset, "/Length key in stream dictionary is not an integer");
- }
-
- length = toS(length_obj.getUIntValue());
- // Seek in two steps to avoid potential integer overflow
- m->file->seek(stream_offset, SEEK_SET);
- m->file->seek(toO(length), SEEK_CUR);
- if (!readToken(m->file).isWord("endstream")) {
- QTC::TC("qpdf", "QPDF missing endstream");
- throw damagedPDF("expected endstream");
- }
- } catch (QPDFExc& e) {
- if (m->attempt_recovery) {
- warn(e);
- length = recoverStreamLength(m->file, og, stream_offset);
- } else {
- throw;
- }
- }
- object = newIndirect(og, QPDF_Stream::create(this, og, object, stream_offset, length));
}
QPDFObjectHandle