mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +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:
parent
315092dd98
commit
afe0242b26
@ -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.
|
||||
|
@ -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))))
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"],
|
||||
)
|
||||
|
4
qpdf/qtest/qpdf/issue-99.out
Normal file
4
qpdf/qtest/qpdf/issue-99.out
Normal 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
|
BIN
qpdf/qtest/qpdf/issue-99.pdf
Normal file
BIN
qpdf/qtest/qpdf/issue-99.pdf
Normal file
Binary file not shown.
5
qpdf/qtest/qpdf/issue-99b.out
Normal file
5
qpdf/qtest/qpdf/issue-99b.out
Normal 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
|
79
qpdf/qtest/qpdf/issue-99b.pdf
Normal file
79
qpdf/qtest/qpdf/issue-99b.pdf
Normal 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
|
Loading…
Reference in New Issue
Block a user