Add basic validation of the 'trailer' dictionary candidates in XRef.indexObjects
(issue 9418)
This patch avoids choosing a (possible) 'trailer' dictionary that `XRef.parse` and/or the `Catalog` constructor/methods will reject anyway. Since `XRef.indexObjects` is already parsing the entire PDF file, the extra dictionary look-ups added here shouldn't matter much. Besides, this is a fallback code-path that only applies to corrupt PDF files anyway.
This commit is contained in:
parent
346810e02a
commit
56e3648b65
@ -1260,7 +1260,7 @@ var XRef = (function XRefClosure() {
|
|||||||
this.readXRef(/* recoveryMode */ true);
|
this.readXRef(/* recoveryMode */ true);
|
||||||
}
|
}
|
||||||
// finding main trailer
|
// finding main trailer
|
||||||
var dict;
|
let trailerDict;
|
||||||
for (i = 0, ii = trailers.length; i < ii; ++i) {
|
for (i = 0, ii = trailers.length; i < ii; ++i) {
|
||||||
stream.pos = trailers[i];
|
stream.pos = trailers[i];
|
||||||
var parser = new Parser(new Lexer(stream), /* allowStreams = */ true,
|
var parser = new Parser(new Lexer(stream), /* allowStreams = */ true,
|
||||||
@ -1270,18 +1270,33 @@ var XRef = (function XRefClosure() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// read the trailer dictionary
|
// read the trailer dictionary
|
||||||
dict = parser.getObj();
|
let dict = parser.getObj();
|
||||||
if (!isDict(dict)) {
|
if (!isDict(dict)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Do some basic validation of the trailer/root dictionary candidate.
|
||||||
|
let rootDict;
|
||||||
|
try {
|
||||||
|
rootDict = dict.get('Root');
|
||||||
|
} catch (ex) {
|
||||||
|
if (ex instanceof MissingDataException) {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!isDict(rootDict) || !rootDict.has('Pages')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// taking the first one with 'ID'
|
// taking the first one with 'ID'
|
||||||
if (dict.has('ID')) {
|
if (dict.has('ID')) {
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
// The current dictionary is a candidate, but continue searching.
|
||||||
|
trailerDict = dict;
|
||||||
}
|
}
|
||||||
// no tailer with 'ID', taking last one (if exists)
|
// No trailer with 'ID', taking last one (if exists).
|
||||||
if (dict) {
|
if (trailerDict) {
|
||||||
return dict;
|
return trailerDict;
|
||||||
}
|
}
|
||||||
// nothing helps
|
// nothing helps
|
||||||
throw new InvalidPDFException('Invalid PDF structure');
|
throw new InvalidPDFException('Invalid PDF structure');
|
||||||
|
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -68,6 +68,7 @@
|
|||||||
!issue9252.pdf
|
!issue9252.pdf
|
||||||
!issue9262_reduced.pdf
|
!issue9262_reduced.pdf
|
||||||
!issue9291.pdf
|
!issue9291.pdf
|
||||||
|
!issue9418.pdf
|
||||||
!issue9458.pdf
|
!issue9458.pdf
|
||||||
!bad-PageLabels.pdf
|
!bad-PageLabels.pdf
|
||||||
!decodeACSuccessive.pdf
|
!decodeACSuccessive.pdf
|
||||||
|
BIN
test/pdfs/issue9418.pdf
Normal file
BIN
test/pdfs/issue9418.pdf
Normal file
Binary file not shown.
@ -748,6 +748,13 @@
|
|||||||
"link": false,
|
"link": false,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "issue9418",
|
||||||
|
"file": "pdfs/issue9418.pdf",
|
||||||
|
"md5": "32ecad8098acb1938539d47944ecb54b",
|
||||||
|
"rounds": 1,
|
||||||
|
"link": false,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "issue9262",
|
{ "id": "issue9262",
|
||||||
"file": "pdfs/issue9262_reduced.pdf",
|
"file": "pdfs/issue9262_reduced.pdf",
|
||||||
"md5": "5347ce2d7b3866625c22e115fd90e0de",
|
"md5": "5347ce2d7b3866625c22e115fd90e0de",
|
||||||
|
Loading…
Reference in New Issue
Block a user