Fallback and try a *previous* generation if all else fails in XRef.indexObjects (issue 15577)

When we fail to find a usable PDF document `trailer` *and* there were errors during parsing, try and fallback to a *previous* generation as a last resort during fetching of uncompressed references.
*Please note:* This will not affect "normal" PDF documents, with valid /XRef data, and even most *corrupt* documents should be completely unaffected by these changes.
This commit is contained in:
Jonas Jenwald 2022-10-16 13:15:07 +02:00
parent 9355b72931
commit de99f99a01
3 changed files with 30 additions and 3 deletions

View File

@ -556,8 +556,15 @@ class XRef {
this.readXRef(/* recoveryMode */ true);
}
// finding main trailer
let trailerDict;
for (const trailer of trailers) {
let trailerDict, trailerError;
for (const trailer of [...trailers, "generationFallback", ...trailers]) {
if (trailer === "generationFallback") {
if (!trailerError) {
break; // No need to fallback if there were no validation errors.
}
this._generationFallback = true;
continue;
}
stream.pos = trailer;
const parser = new Parser({
lexer: new Lexer(stream),
@ -590,6 +597,7 @@ class XRef {
}
// The top-level /Pages dictionary isn't obviously corrupt.
} catch (ex) {
trailerError = ex;
continue;
}
// taking the first one with 'ID'
@ -780,7 +788,17 @@ class XRef {
const gen = ref.gen;
let num = ref.num;
if (xrefEntry.gen !== gen) {
throw new XRefEntryException(`Inconsistent generation in XRef: ${ref}`);
const msg = `Inconsistent generation in XRef: ${ref}`;
// Try falling back to a *previous* generation (fixes issue15577.pdf).
if (this._generationFallback && xrefEntry.gen < gen) {
warn(msg);
return this.fetchUncompressed(
Ref.get(num, xrefEntry.gen),
xrefEntry,
suppressEncryption
);
}
throw new XRefEntryException(msg);
}
const stream = this.stream.makeSubStream(
xrefEntry.offset + this.stream.start

View File

@ -0,0 +1 @@
https://github.com/mozilla/pdf.js/files/9813960/hang-080214-152005-90.pdf

View File

@ -661,6 +661,14 @@
"lastPage": 1,
"type": "eq"
},
{ "id": "issue15577",
"file": "pdfs/issue15577.pdf",
"md5": "6939244cf44b7b31ff960b58ed7e4004",
"link": true,
"rounds": 1,
"lastPage": 1,
"type": "eq"
},
{ "id": "hmm-pdf",
"file": "pdfs/hmm.pdf",
"md5": "e08467e60101ee5f4a59716e86db6dc9",