aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--libqpdf/QPDF.cc8
-rw-r--r--libqpdf/QPDFObjectHandle.cc10
-rw-r--r--qpdf/qpdf.testcov3
-rw-r--r--qpdf/qtest/qpdf.test4
-rw-r--r--qpdf/qtest/qpdf/issue-99.out4
-rw-r--r--qpdf/qtest/qpdf/issue-99.pdfbin0 -> 4798 bytes
-rw-r--r--qpdf/qtest/qpdf/issue-99b.out5
-rw-r--r--qpdf/qtest/qpdf/issue-99b.pdf79
9 files changed, 116 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index ce0ce1e7..f39c52c3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2017-07-26 Jay Berkenbilt <ejb@ql.org>
+ * CVE-2017-9208: Handle references to and appearance of object 0
+ as a special case. Object 0 is not allowed, and qpdf was using it
+ internally to represent direct objects.
+
* CVE-2017-9209: Fix infinite loop caused by attempting to
reconstruct the xref table while already in the process of
reconstructing the xref table.
diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc
index a50c87ad..846f188f 100644
--- a/libqpdf/QPDF.cc
+++ b/libqpdf/QPDF.cc
@@ -1350,6 +1350,14 @@ QPDF::readObjectAtOffset(bool try_recovery,
objid = atoi(tobjid.getValue().c_str());
generation = atoi(tgen.getValue().c_str());
+ if (objid == 0)
+ {
+ QTC::TC("qpdf", "QPDF object id 0");
+ throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
+ this->last_object_description, offset,
+ "object with ID 0");
+ }
+
if ((exp_objid >= 0) &&
(! ((objid == exp_objid) && (generation == exp_generation))))
{
diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc
index 687ba439..cd3084cb 100644
--- a/libqpdf/QPDFObjectHandle.cc
+++ b/libqpdf/QPDFObjectHandle.cc
@@ -1089,6 +1089,16 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
QPDFObjectHandle
QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation)
{
+ if (objid == 0)
+ {
+ // Special case: QPDF uses objid 0 as a sentinel for direct
+ // objects, and the PDF specification doesn't allow for object
+ // 0. Treat indirect references to object 0 as null so that we
+ // never create an indirect object with objid 0.
+ QTC::TC("qpdf", "QPDFObjectHandle indirect with 0 objid");
+ return newNull();
+ }
+
return QPDFObjectHandle(qpdf, objid, generation);
}
diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov
index d43939ea..f3ddd60d 100644
--- a/qpdf/qpdf.testcov
+++ b/qpdf/qpdf.testcov
@@ -273,3 +273,6 @@ QPDFWriter standard deterministic ID 1
QPDFWriter linearized deterministic ID 1
QPDFWriter deterministic with no data 0
qpdf-c called qpdf_set_deterministic_ID 0
+QPDFObjectHandle indirect with 0 objid 0
+QPDF object id 0 0
+QPDF caught recursive xref reconstruction 0
diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test
index dd8dad30..c45215fa 100644
--- a/qpdf/qtest/qpdf.test
+++ b/qpdf/qtest/qpdf.test
@@ -206,7 +206,7 @@ $td->runtest("remove page we don't have",
show_ntests();
# ----------
$td->notify("--- Miscellaneous Tests ---");
-$n_tests += 79;
+$n_tests += 81;
$td->runtest("qpdf version",
{$td->COMMAND => "qpdf --version"},
@@ -220,6 +220,8 @@ $td->runtest("C API: qpdf version",
# Files to reproduce various bugs
foreach my $d (
+ ["99", "object 0"],
+ ["99b", "object 0"],
["100","xref reconstruction loop"],
["101", "resolve for exception text"],
)
diff --git a/qpdf/qtest/qpdf/issue-99.out b/qpdf/qtest/qpdf/issue-99.out
new file mode 100644
index 00000000..89d6e174
--- /dev/null
+++ b/qpdf/qtest/qpdf/issue-99.out
@@ -0,0 +1,4 @@
+WARNING: issue-99.pdf: file is damaged
+WARNING: issue-99.pdf (file position 3526): xref not found
+WARNING: issue-99.pdf: Attempting to reconstruct cross-reference table
+operation for Dictionary object attempted on object of wrong type
diff --git a/qpdf/qtest/qpdf/issue-99.pdf b/qpdf/qtest/qpdf/issue-99.pdf
new file mode 100644
index 00000000..3f370176
--- /dev/null
+++ b/qpdf/qtest/qpdf/issue-99.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/issue-99b.out b/qpdf/qtest/qpdf/issue-99b.out
new file mode 100644
index 00000000..355701be
--- /dev/null
+++ b/qpdf/qtest/qpdf/issue-99b.out
@@ -0,0 +1,5 @@
+WARNING: issue-99b.pdf: file is damaged
+WARNING: issue-99b.pdf (object 1 0, file position 9): object with ID 0
+WARNING: issue-99b.pdf: Attempting to reconstruct cross-reference table
+WARNING: issue-99b.pdf: object 1 0 not found in file after regenerating cross reference table
+operation for Dictionary object attempted on object of wrong type
diff --git a/qpdf/qtest/qpdf/issue-99b.pdf b/qpdf/qtest/qpdf/issue-99b.pdf
new file mode 100644
index 00000000..fcf275f8
--- /dev/null
+++ b/qpdf/qtest/qpdf/issue-99b.pdf
@@ -0,0 +1,79 @@
+%PDF-1.3
+0 0 obj
+<<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+
+2 0 obj
+<<
+ /Type /Pages
+ /Kids [
+ 3 0 R
+ ]
+ /Count 1
+>>
+endobj
+
+3 0 obj
+<<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /Contents 4 0 R
+ /Resources <<
+ /ProcSet 5 0 R
+ /Font <<
+ /F1 6 0 R
+ >>
+ >>
+>>
+endobj
+
+4 0 obj
+<<
+ /Length 44
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+
+5 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+6 0 obj
+<<
+ /Type /Font
+ /Subtype /Type1
+ /Name /F1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+
+xref
+0 7
+0000000000 65535 f
+0000000009 00000 n
+0000000063 00000 n
+0000000135 00000 n
+0000000307 00000 n
+0000000403 00000 n
+0000000438 00000 n
+trailer <<
+ /Size 7
+ /Root 1 0 R
+>>
+startxref
+556
+%%EOF