diff --git a/src/stream.js b/src/stream.js index 1067e42c7..4a9c1dabe 100644 --- a/src/stream.js +++ b/src/stream.js @@ -1201,66 +1201,53 @@ var AsciiHexStream = (function AsciiHexStreamClosure() { this.str = str; this.dict = str.dict; + this.firstDigit = -1; + DecodeStream.call(this); } - var hexvalueMap = { - 9: -1, // \t - 32: -1, // space - 48: 0, - 49: 1, - 50: 2, - 51: 3, - 52: 4, - 53: 5, - 54: 6, - 55: 7, - 56: 8, - 57: 9, - 65: 10, - 66: 11, - 67: 12, - 68: 13, - 69: 14, - 70: 15, - 97: 10, - 98: 11, - 99: 12, - 100: 13, - 101: 14, - 102: 15 - }; - AsciiHexStream.prototype = Object.create(DecodeStream.prototype); AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() { - var gtCode = '>'.charCodeAt(0), bytes = this.str.getBytes(), c, n, - decodeLength, buffer, bufferLength, i, length; - - decodeLength = (bytes.length + 1) >> 1; - buffer = this.ensureBuffer(this.bufferLength + decodeLength); - bufferLength = this.bufferLength; - - for (i = 0, length = bytes.length; i < length; i++) { - c = hexvalueMap[bytes[i]]; - while (c == -1 && (i + 1) < length) { - c = hexvalueMap[bytes[++i]]; - } - - if ((i + 1) < length && (bytes[i + 1] !== gtCode)) { - n = hexvalueMap[bytes[++i]]; - buffer[bufferLength++] = c * 16 + n; - } else { - // EOD marker at an odd number, behave as if a 0 followed the last - // digit. - if (bytes[i] !== gtCode) { - buffer[bufferLength++] = c * 16; - } - } + var UPSTREAM_BLOCK_SIZE = 8000; + var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE); + if (!bytes.length) { + this.eof = true; + return; } + var maxDecodeLength = (bytes.length + 1) >> 1; + var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength); + var bufferLength = this.bufferLength; + + var firstDigit = this.firstDigit; + for (var i = 0, ii = bytes.length; i < ii; i++) { + var ch = bytes[i], digit; + if (ch >= 0x30 && ch <= 0x39) { // '0'-'9' + digit = ch & 0x0F; + } else if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) { + // 'A'-'Z', 'a'-'z' + digit = (ch & 0x0F) + 9; + } else if (ch === 0x3E) { // '>' + this.eof = true; + break; + } else { // probably whitespace + continue; // ignoring + } + if (firstDigit < 0) { + firstDigit = digit; + } else { + buffer[bufferLength++] = (firstDigit << 4) | digit; + firstDigit = -1; + } + } + if (firstDigit >= 0 && this.eof) { + // incomplete byte + buffer[bufferLength++] = (firstDigit << 4); + firstDigit = -1; + } + this.firstDigit = firstDigit; this.bufferLength = bufferLength; - this.eof = true; }; return AsciiHexStream; diff --git a/test/pdfs/bug889327.pdf.link b/test/pdfs/bug889327.pdf.link new file mode 100644 index 000000000..4590a69a7 --- /dev/null +++ b/test/pdfs/bug889327.pdf.link @@ -0,0 +1 @@ +https://bugzilla.mozilla.org/attachment.cgi?id=770134 diff --git a/test/test_manifest.json b/test/test_manifest.json index 97d622650..836c826ff 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -1252,6 +1252,14 @@ "rounds": 1, "type": "eq" }, + { "id": "bug889327", + "file": "pdfs/bug889327.pdf", + "md5": "b45cd63419241c40731f98d0e1dac082", + "link": true, + "lastPage": 1, + "rounds": 1, + "type": "eq" + }, { "id": "issue2829", "file": "pdfs/issue2829.pdf", "md5": "f32b28cf8792f6ccc470446bfbb38584",