diff --git a/src/core/parser.js b/src/core/parser.js index c40f36a8298b8..94b2e7894cbcd 100644 --- a/src/core/parser.js +++ b/src/core/parser.js @@ -1163,8 +1163,8 @@ class Lexer { const strBuf = this.strBuf; strBuf.length = 0; let ch = this.currentChar; - let isFirstHex = true; - let firstDigit, secondDigit; + let firstDigit = -1, + digit = -1; this._hexStringNumWarn = 0; while (true) { @@ -1178,26 +1178,25 @@ class Lexer { ch = this.nextChar(); continue; } else { - if (isFirstHex) { - firstDigit = toHexDigit(ch); - if (firstDigit === -1) { - this._hexStringWarn(ch); - ch = this.nextChar(); - continue; - } + digit = toHexDigit(ch); + if (digit === -1) { + this._hexStringWarn(ch); + } else if (firstDigit === -1) { + firstDigit = digit; } else { - secondDigit = toHexDigit(ch); - if (secondDigit === -1) { - this._hexStringWarn(ch); - ch = this.nextChar(); - continue; - } - strBuf.push(String.fromCharCode((firstDigit << 4) | secondDigit)); + strBuf.push(String.fromCharCode((firstDigit << 4) | digit)); + firstDigit = -1; } - isFirstHex = !isFirstHex; ch = this.nextChar(); } } + + // According to the PDF spec, section "7.3.4.3 Hexadecimal Strings": + // "If the final digit of a hexadecimal string is missing—that is, if there + // is an odd number of digits—the final digit shall be assumed to be 0." + if (firstDigit !== -1) { + strBuf.push(String.fromCharCode(firstDigit << 4)); + } return strBuf.join(""); } diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index af276cad181cd..98581ffbafbc0 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -564,6 +564,7 @@ !poppler-90-0-fuzzed.pdf !issue14415.pdf !issue14307.pdf +!issue18645.pdf !issue14497.pdf !bug1799927.pdf !issue14502.pdf diff --git a/test/pdfs/issue18645.pdf b/test/pdfs/issue18645.pdf new file mode 100644 index 0000000000000..deb824088d455 Binary files /dev/null and b/test/pdfs/issue18645.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index 82e0024cb4472..57f5a9f7aa011 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -7986,6 +7986,13 @@ } } }, + { + "id": "issue18645", + "file": "pdfs/issue18645.pdf", + "md5": "ad05b63db4f21f612adb0900093a3e34", + "rounds": 1, + "type": "eq" + }, { "id": "bug857031", "file": "pdfs/bug857031.pdf", diff --git a/test/unit/parser_spec.js b/test/unit/parser_spec.js index b286dde8602ff..404d729a15a10 100644 --- a/test/unit/parser_spec.js +++ b/test/unit/parser_spec.js @@ -201,11 +201,12 @@ describe("parser", function () { }); describe("getHexString", function () { - it("should not throw exception on bad input", function () { - // '7 0 2 15 5 2 2 2 4 3 2 4' should be parsed as '70 21 55 22 24 32'. + it("should handle an odd number of digits", function () { + // '7 0 2 15 5 2 2 2 4 3 2 4' should be parsed as + // '70 21 55 22 24 32 40'. const input = new StringStream("<7 0 2 15 5 2 2 2 4 3 2 4>"); const lexer = new Lexer(input); - expect(lexer.getHexString()).toEqual('p!U"$2'); + expect(lexer.getHexString()).toEqual('p!U"$2@'); }); });