2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-06-04 03:10:52 +00:00

Handle object ID 0 (fixes #99)

This is CVE-2017-9208.

The QPDF library uses object ID 0 internally as a sentinel to
represent a direct object, but prior to this fix, was not blocking
handling of 0 0 obj or 0 0 R as a special case. Creating an object in
the file with 0 0 obj could cause various infinite loops. The PDF spec
doesn't allow for object 0. Having qpdf handle object 0 might be a
better fix, but changing all the places in the code that assumes objid
== 0 means direct would be risky.
This commit is contained in:
Jay Berkenbilt 2017-07-26 04:30:32 -04:00
parent 315092dd98
commit afe0242b26
9 changed files with 116 additions and 1 deletions

View File

@ -1,5 +1,9 @@
2017-07-26 Jay Berkenbilt <ejb@ql.org> 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 * CVE-2017-9209: Fix infinite loop caused by attempting to
reconstruct the xref table while already in the process of reconstruct the xref table while already in the process of
reconstructing the xref table. reconstructing the xref table.

View File

@ -1350,6 +1350,14 @@ QPDF::readObjectAtOffset(bool try_recovery,
objid = atoi(tobjid.getValue().c_str()); objid = atoi(tobjid.getValue().c_str());
generation = atoi(tgen.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) && if ((exp_objid >= 0) &&
(! ((objid == exp_objid) && (generation == exp_generation)))) (! ((objid == exp_objid) && (generation == exp_generation))))
{ {

View File

@ -1089,6 +1089,16 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
QPDFObjectHandle QPDFObjectHandle
QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation) 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); return QPDFObjectHandle(qpdf, objid, generation);
} }

View File

@ -273,3 +273,6 @@ QPDFWriter standard deterministic ID 1
QPDFWriter linearized deterministic ID 1 QPDFWriter linearized deterministic ID 1
QPDFWriter deterministic with no data 0 QPDFWriter deterministic with no data 0
qpdf-c called qpdf_set_deterministic_ID 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

View File

@ -206,7 +206,7 @@ $td->runtest("remove page we don't have",
show_ntests(); show_ntests();
# ---------- # ----------
$td->notify("--- Miscellaneous Tests ---"); $td->notify("--- Miscellaneous Tests ---");
$n_tests += 79; $n_tests += 81;
$td->runtest("qpdf version", $td->runtest("qpdf version",
{$td->COMMAND => "qpdf --version"}, {$td->COMMAND => "qpdf --version"},
@ -220,6 +220,8 @@ $td->runtest("C API: qpdf version",
# Files to reproduce various bugs # Files to reproduce various bugs
foreach my $d ( foreach my $d (
["99", "object 0"],
["99b", "object 0"],
["100","xref reconstruction loop"], ["100","xref reconstruction loop"],
["101", "resolve for exception text"], ["101", "resolve for exception text"],
) )

View File

@ -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

Binary file not shown.

View File

@ -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

View File

@ -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