mirror of
https://github.com/qpdf/qpdf.git
synced 2025-01-02 22:50:20 +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:
parent
eae8370cd9
commit
16051788ed
@ -1,5 +1,11 @@
|
||||
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.
|
||||
This key is optional, but some version of MacOS reportedly fail to
|
||||
open encrypted PDF files without this key.
|
||||
|
@ -958,6 +958,15 @@ QPDF::checkHOutlines(std::list<std::string>& warnings)
|
||||
{
|
||||
// Check length and offset. Acrobat gets these wrong.
|
||||
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());
|
||||
assert(this->xref_table.count(og) > 0);
|
||||
int offset = getLinearizationOffset(og);
|
||||
|
@ -68,6 +68,20 @@ QPDF::optimize(std::map<int, int> const& object_stream_data,
|
||||
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
|
||||
// page level. This also initializes this->all_pages.
|
||||
pushInheritedAttributesToPage(allow_changes, false);
|
||||
@ -97,7 +111,6 @@ QPDF::optimize(std::map<int, int> const& object_stream_data,
|
||||
}
|
||||
}
|
||||
|
||||
QPDFObjectHandle root = getRoot();
|
||||
keys = root.getKeys();
|
||||
for (std::set<std::string>::iterator iter = keys.begin();
|
||||
iter != keys.end(); ++iter)
|
||||
|
@ -263,3 +263,4 @@ QPDFObjectHandle EOF in inline image 0
|
||||
QPDFObjectHandle inline image token 0
|
||||
QPDF not caching overridden objstm object 0
|
||||
QPDFWriter original obj non-zero gen 0
|
||||
QPDF_optimization indirect outlines 0
|
||||
|
@ -1192,6 +1192,7 @@ my @to_linearize =
|
||||
'object-stream', # contains object streams
|
||||
'hybrid-xref', # contains both xref tables and streams
|
||||
'gen1', # has objects with generation > 0
|
||||
'direct-outlines', # /Outlines is a direct object
|
||||
@linearized_files, # we should be able to relinearize
|
||||
);
|
||||
|
||||
|
1503
qpdf/qtest/qpdf/direct-outlines.pdf
Normal file
1503
qpdf/qtest/qpdf/direct-outlines.pdf
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user