2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-05-31 09:20:52 +00:00

Handle /Outlines dictionary being a direct object

Even though this case is not valid according to the spec, it has been
seen, and caused an internal error.
This commit is contained in:
Jay Berkenbilt 2013-06-14 21:35:10 -04:00
parent eae8370cd9
commit 16051788ed
6 changed files with 1534 additions and 1 deletions

View File

@ -1,5 +1,11 @@
2013-06-14 Jay Berkenbilt <ejb@ql.org> 2013-06-14 Jay Berkenbilt <ejb@ql.org>
* Detect and correct /Outlines dictionary being a direct object
when linearizing files. This is not allowed by the spec but has
been seen in the wild. Prior to this change, such a file would
cause an internal error in the linearization code, which assumed
/Outlines was indirect.
* Add /Length key to crypt filter dictionary for encrypted files. * Add /Length key to crypt filter dictionary for encrypted files.
This key is optional, but some version of MacOS reportedly fail to This key is optional, but some version of MacOS reportedly fail to
open encrypted PDF files without this key. open encrypted PDF files without this key.

View File

@ -958,6 +958,15 @@ QPDF::checkHOutlines(std::list<std::string>& warnings)
{ {
// Check length and offset. Acrobat gets these wrong. // Check length and offset. Acrobat gets these wrong.
QPDFObjectHandle outlines = getRoot().getKey("/Outlines"); QPDFObjectHandle outlines = getRoot().getKey("/Outlines");
if (! outlines.isIndirect())
{
// This case is not exercised in test suite since not
// permitted by the spec, but if this does occur, the
// code below would fail.
warnings.push_back(
"/Outlines key of root dictionary is not indirect");
return;
}
QPDFObjGen og(outlines.getObjGen()); QPDFObjGen og(outlines.getObjGen());
assert(this->xref_table.count(og) > 0); assert(this->xref_table.count(og) > 0);
int offset = getLinearizationOffset(og); int offset = getLinearizationOffset(og);

View File

@ -68,6 +68,20 @@ QPDF::optimize(std::map<int, int> const& object_stream_data,
return; return;
} }
// The PDF specification indicates that /Outlines is supposed to
// be an indirect reference. Force it to be so if it exists and
// is direct. (This has been seen in the wild.)
QPDFObjectHandle root = getRoot();
if (root.getKey("/Outlines").isDictionary())
{
QPDFObjectHandle outlines = root.getKey("/Outlines");
if (! outlines.isIndirect())
{
QTC::TC("qpdf", "QPDF_optimization indirect outlines");
root.replaceKey("/Outlines", makeIndirectObject(outlines));
}
}
// Traverse pages tree pushing all inherited resources down to the // Traverse pages tree pushing all inherited resources down to the
// page level. This also initializes this->all_pages. // page level. This also initializes this->all_pages.
pushInheritedAttributesToPage(allow_changes, false); pushInheritedAttributesToPage(allow_changes, false);
@ -97,7 +111,6 @@ QPDF::optimize(std::map<int, int> const& object_stream_data,
} }
} }
QPDFObjectHandle root = getRoot();
keys = root.getKeys(); keys = root.getKeys();
for (std::set<std::string>::iterator iter = keys.begin(); for (std::set<std::string>::iterator iter = keys.begin();
iter != keys.end(); ++iter) iter != keys.end(); ++iter)

View File

@ -263,3 +263,4 @@ QPDFObjectHandle EOF in inline image 0
QPDFObjectHandle inline image token 0 QPDFObjectHandle inline image token 0
QPDF not caching overridden objstm object 0 QPDF not caching overridden objstm object 0
QPDFWriter original obj non-zero gen 0 QPDFWriter original obj non-zero gen 0
QPDF_optimization indirect outlines 0

View File

@ -1192,6 +1192,7 @@ my @to_linearize =
'object-stream', # contains object streams 'object-stream', # contains object streams
'hybrid-xref', # contains both xref tables and streams 'hybrid-xref', # contains both xref tables and streams
'gen1', # has objects with generation > 0 'gen1', # has objects with generation > 0
'direct-outlines', # /Outlines is a direct object
@linearized_files, # we should be able to relinearize @linearized_files, # we should be able to relinearize
); );

File diff suppressed because it is too large Load Diff