Merge pull request #11680 from Snuffleupagus/hasBlendModes-fetch-errors

Prevent lookup errors in `PartialEvaluator.hasBlendModes` from breaking all parsing/rendering of a page (issue 11678)
This commit is contained in:
Tim van der Meij 2020-03-09 23:04:28 +01:00 committed by GitHub
commit af8d0b9597
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 5 deletions

View File

@ -61,6 +61,7 @@ import {
WinAnsiEncoding, WinAnsiEncoding,
ZapfDingbatsEncoding, ZapfDingbatsEncoding,
} from "./encodings.js"; } from "./encodings.js";
import { getLookupTableFactory, MissingDataException } from "./core_utils.js";
import { import {
getNormalizedUnicodes, getNormalizedUnicodes,
getUnicodeForGlyph, getUnicodeForGlyph,
@ -77,7 +78,6 @@ import { bidi } from "./bidi.js";
import { ColorSpace } from "./colorspace.js"; import { ColorSpace } from "./colorspace.js";
import { DecodeStream } from "./stream.js"; import { DecodeStream } from "./stream.js";
import { getGlyphsUnicode } from "./glyphlist.js"; import { getGlyphsUnicode } from "./glyphlist.js";
import { getLookupTableFactory } from "./core_utils.js";
import { getMetrics } from "./metrics.js"; import { getMetrics } from "./metrics.js";
import { isPDFFunction } from "./function.js"; import { isPDFFunction } from "./function.js";
import { JpegStream } from "./jpeg_stream.js"; import { JpegStream } from "./jpeg_stream.js";
@ -266,7 +266,27 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
if (processed[graphicState.toString()]) { if (processed[graphicState.toString()]) {
continue; // The ExtGState has already been processed. continue; // The ExtGState has already been processed.
} }
graphicState = xref.fetch(graphicState); try {
graphicState = xref.fetch(graphicState);
} catch (ex) {
if (ex instanceof MissingDataException) {
throw ex;
}
if (this.options.ignoreErrors) {
if (graphicState instanceof Ref) {
// Avoid parsing a corrupt ExtGState more than once.
processed[graphicState.toString()] = true;
}
// Error(s) in the ExtGState -- sending unsupported feature
// notification and allow parsing/rendering to continue.
this.handler.send("UnsupportedFeature", {
featureId: UNSUPPORTED_FEATURES.unknown,
});
warn(`hasBlendModes - ignoring ExtGState: "${ex}".`);
continue;
}
throw ex;
}
} }
if (!(graphicState instanceof Dict)) { if (!(graphicState instanceof Dict)) {
continue; continue;
@ -308,7 +328,27 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
// time for badly generated PDF files (fixes issue6961.pdf). // time for badly generated PDF files (fixes issue6961.pdf).
continue; continue;
} }
xObject = xref.fetch(xObject); try {
xObject = xref.fetch(xObject);
} catch (ex) {
if (ex instanceof MissingDataException) {
throw ex;
}
if (this.options.ignoreErrors) {
if (xObject instanceof Ref) {
// Avoid parsing a corrupt XObject more than once.
processed[xObject.toString()] = true;
}
// Error(s) in the XObject -- sending unsupported feature
// notification and allow parsing/rendering to continue.
this.handler.send("UnsupportedFeature", {
featureId: UNSUPPORTED_FEATURES.unknown,
});
warn(`hasBlendModes - ignoring XObject: "${ex}".`);
continue;
}
throw ex;
}
} }
if (!isStream(xObject)) { if (!isStream(xObject)) {
continue; continue;

View File

@ -842,6 +842,7 @@ class Lexer {
// other commands or literals as a prefix. The knowCommands is optional. // other commands or literals as a prefix. The knowCommands is optional.
this.knownCommands = knownCommands; this.knownCommands = knownCommands;
this._hexStringNumWarn = 0;
this.beginInlineImagePos = -1; this.beginInlineImagePos = -1;
} }
@ -1099,12 +1100,32 @@ class Lexer {
return Name.get(strBuf.join("")); return Name.get(strBuf.join(""));
} }
/**
* @private
*/
_hexStringWarn(ch) {
const MAX_HEX_STRING_NUM_WARN = 5;
if (this._hexStringNumWarn++ === MAX_HEX_STRING_NUM_WARN) {
warn("getHexString - ignoring additional invalid characters.");
return;
}
if (this._hexStringNumWarn > MAX_HEX_STRING_NUM_WARN) {
// Limit the number of warning messages printed for a `this.getHexString`
// invocation, since corrupt PDF documents may otherwise spam the console
// enough to affect general performance negatively.
return;
}
warn(`getHexString - ignoring invalid character: ${ch}`);
}
getHexString() { getHexString() {
const strBuf = this.strBuf; const strBuf = this.strBuf;
strBuf.length = 0; strBuf.length = 0;
let ch = this.currentChar; let ch = this.currentChar;
let isFirstHex = true; let isFirstHex = true;
let firstDigit, secondDigit; let firstDigit, secondDigit;
this._hexStringNumWarn = 0;
while (true) { while (true) {
if (ch < 0) { if (ch < 0) {
@ -1120,14 +1141,14 @@ class Lexer {
if (isFirstHex) { if (isFirstHex) {
firstDigit = toHexDigit(ch); firstDigit = toHexDigit(ch);
if (firstDigit === -1) { if (firstDigit === -1) {
warn(`Ignoring invalid character "${ch}" in hex string`); this._hexStringWarn(ch);
ch = this.nextChar(); ch = this.nextChar();
continue; continue;
} }
} else { } else {
secondDigit = toHexDigit(ch); secondDigit = toHexDigit(ch);
if (secondDigit === -1) { if (secondDigit === -1) {
warn(`Ignoring invalid character "${ch}" in hex string`); this._hexStringWarn(ch);
ch = this.nextChar(); ch = this.nextChar();
continue; continue;
} }

View File

@ -0,0 +1 @@
https://github.com/mozilla/pdf.js/files/4304559/default.pdf

View File

@ -3064,6 +3064,15 @@
"link": false, "link": false,
"type": "eq" "type": "eq"
}, },
{ "id": "issue11678",
"file": "pdfs/issue11678.pdf",
"md5": "e2efadeb91932f4c21e4fc682cce7de9",
"rounds": 1,
"link": true,
"firstPage": 2,
"lastPage": 2,
"type": "eq"
},
{ "id": "issue4890", { "id": "issue4890",
"file": "pdfs/issue4890.pdf", "file": "pdfs/issue4890.pdf",
"md5": "1666feb4cd26318c2bdbea6a175dce87", "md5": "1666feb4cd26318c2bdbea6a175dce87",