mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
Merge pull request #9827 from Snuffleupagus/misc-corrupt-pdf-fixes
Fix various corrupt PDF files (issue 9252, issue 9418)
This commit is contained in:
commit
98ea39f9d0
7 changed files with 194 additions and 20 deletions
|
@ -855,7 +855,16 @@ var XRef = (function XRefClosure() {
|
|||
}
|
||||
trailerDict.assignXref(this);
|
||||
this.trailer = trailerDict;
|
||||
var encrypt = trailerDict.get('Encrypt');
|
||||
|
||||
let encrypt;
|
||||
try {
|
||||
encrypt = trailerDict.get('Encrypt');
|
||||
} catch (ex) {
|
||||
if (ex instanceof MissingDataException) {
|
||||
throw ex;
|
||||
}
|
||||
warn(`XRef.parse - Invalid "Encrypt" reference: "${ex}".`);
|
||||
}
|
||||
if (isDict(encrypt)) {
|
||||
var ids = trailerDict.get('ID');
|
||||
var fileId = (ids && ids.length) ? ids[0] : '';
|
||||
|
@ -868,8 +877,22 @@ var XRef = (function XRefClosure() {
|
|||
this.pdfManager.password);
|
||||
}
|
||||
|
||||
// get the root dictionary (catalog) object
|
||||
if (!(this.root = trailerDict.get('Root'))) {
|
||||
// Get the root dictionary (catalog) object, and do some basic validation.
|
||||
let root;
|
||||
try {
|
||||
root = trailerDict.get('Root');
|
||||
} catch (ex) {
|
||||
if (ex instanceof MissingDataException) {
|
||||
throw ex;
|
||||
}
|
||||
warn(`XRef.parse - Invalid "Root" reference: "${ex}".`);
|
||||
}
|
||||
if (isDict(root) && root.has('Pages')) {
|
||||
this.root = root;
|
||||
} else {
|
||||
if (!recoveryMode) {
|
||||
throw new XRefParseException();
|
||||
}
|
||||
throw new FormatError('Invalid root reference');
|
||||
}
|
||||
},
|
||||
|
@ -1208,7 +1231,7 @@ var XRef = (function XRefClosure() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
startPos += contentLength;
|
||||
startPos = endPos;
|
||||
}
|
||||
let content = buffer.subarray(position, position + contentLength);
|
||||
|
||||
|
@ -1237,7 +1260,7 @@ var XRef = (function XRefClosure() {
|
|||
this.readXRef(/* recoveryMode */ true);
|
||||
}
|
||||
// finding main trailer
|
||||
var dict;
|
||||
let trailerDict;
|
||||
for (i = 0, ii = trailers.length; i < ii; ++i) {
|
||||
stream.pos = trailers[i];
|
||||
var parser = new Parser(new Lexer(stream), /* allowStreams = */ true,
|
||||
|
@ -1247,18 +1270,33 @@ var XRef = (function XRefClosure() {
|
|||
continue;
|
||||
}
|
||||
// read the trailer dictionary
|
||||
dict = parser.getObj();
|
||||
let dict = parser.getObj();
|
||||
if (!isDict(dict)) {
|
||||
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'
|
||||
if (dict.has('ID')) {
|
||||
return dict;
|
||||
}
|
||||
// The current dictionary is a candidate, but continue searching.
|
||||
trailerDict = dict;
|
||||
}
|
||||
// no tailer with 'ID', taking last one (if exists)
|
||||
if (dict) {
|
||||
return dict;
|
||||
// No trailer with 'ID', taking last one (if exists).
|
||||
if (trailerDict) {
|
||||
return trailerDict;
|
||||
}
|
||||
// nothing helps
|
||||
throw new InvalidPDFException('Invalid PDF structure');
|
||||
|
|
|
@ -18,8 +18,8 @@ import {
|
|||
PredictorStream, RunLengthStream
|
||||
} from './stream';
|
||||
import {
|
||||
assert, FormatError, info, isNum, isString, MissingDataException, StreamType,
|
||||
warn
|
||||
assert, FormatError, info, isNum, isSpace, isString, MissingDataException,
|
||||
StreamType, warn
|
||||
} from '../shared/util';
|
||||
import {
|
||||
Cmd, Dict, EOF, isCmd, isDict, isEOF, isName, Name, Ref
|
||||
|
@ -721,7 +721,7 @@ var Lexer = (function LexerClosure() {
|
|||
var ch = this.currentChar;
|
||||
var eNotation = false;
|
||||
var divideBy = 0; // different from 0 if it's a floating point value
|
||||
var sign = 1;
|
||||
var sign = 0;
|
||||
|
||||
if (ch === 0x2D) { // '-'
|
||||
sign = -1;
|
||||
|
@ -732,10 +732,7 @@ var Lexer = (function LexerClosure() {
|
|||
ch = this.nextChar();
|
||||
}
|
||||
} else if (ch === 0x2B) { // '+'
|
||||
ch = this.nextChar();
|
||||
}
|
||||
if (ch === 0x2E) { // '.'
|
||||
divideBy = 10;
|
||||
sign = 1;
|
||||
ch = this.nextChar();
|
||||
}
|
||||
if (ch === 0x0A || ch === 0x0D) { // LF, CR
|
||||
|
@ -744,11 +741,22 @@ var Lexer = (function LexerClosure() {
|
|||
ch = this.nextChar();
|
||||
} while (ch === 0x0A || ch === 0x0D);
|
||||
}
|
||||
if (ch === 0x2E) { // '.'
|
||||
divideBy = 10;
|
||||
ch = this.nextChar();
|
||||
}
|
||||
if (ch < 0x30 || ch > 0x39) { // '0' - '9'
|
||||
if (divideBy === 10 && sign === 0 &&
|
||||
(isSpace(ch) || ch === /* EOF = */ -1)) {
|
||||
// This is consistent with Adobe Reader (fixes issue9252.pdf).
|
||||
warn('Lexer.getNumber - treating a single decimal point as zero.');
|
||||
return 0;
|
||||
}
|
||||
throw new FormatError(
|
||||
`Invalid number: ${String.fromCharCode(ch)} (charCode ${ch})`);
|
||||
}
|
||||
|
||||
sign = sign || 1;
|
||||
var baseValue = ch - 0x30; // '0'
|
||||
var powerValue = 0;
|
||||
var powerValueSign = 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue