diff --git a/src/chunked_stream.js b/src/chunked_stream.js index 8d8811bd1..625dbc18d 100644 --- a/src/chunked_stream.js +++ b/src/chunked_stream.js @@ -141,6 +141,12 @@ var ChunkedStream = (function ChunkedStreamClosure() { return bytes.subarray(pos, end); }, + peekBytes: function ChunkedStream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + getByteRange: function ChunkedStream_getBytes(begin, end) { this.ensureRange(begin, end); return this.bytes.subarray(begin, end); diff --git a/src/parser.js b/src/parser.js index 72747e524..d12d36ebd 100644 --- a/src/parser.js +++ b/src/parser.js @@ -209,9 +209,46 @@ var Parser = (function ParserClosure() { this.shift(); // '>>' this.shift(); // 'stream' if (!isCmd(this.buf1, 'endstream')) { - warn('Missing endstream'); + // bad stream length, scanning for endstream + stream.pos = pos; + var SCAN_BLOCK_SIZE = 2048; + var ENDSTREAM_SIGNATURE_LENGTH = 9; + var ENDSTREAM_SIGNATURE = [0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6D]; + var skipped = 0, found = false; + while (stream.pos < stream.end) { + var scanBytes = stream.peekBytes(SCAN_BLOCK_SIZE); + var scanLength = scanBytes.length - ENDSTREAM_SIGNATURE_LENGTH; + var found = false, i, ii, j; + for (i = 0, j = 0; i < scanLength; i++) { + var b = scanBytes[i]; + if (b !== ENDSTREAM_SIGNATURE[j]) { + i -= j; + j = 0; + } else { + j++; + if (j >= ENDSTREAM_SIGNATURE_LENGTH) { + found = true; + break; + } + } + } + if (found) { + skipped += i - ENDSTREAM_SIGNATURE_LENGTH; + stream.pos += i - ENDSTREAM_SIGNATURE_LENGTH; + break; + } + skipped += scanLength; + stream.pos += scanLength; + } + if (!found) { + error('Missing endstream'); + } + length = skipped; + this.shift(); + this.shift(); } - this.shift(); + this.shift(); // 'endstream' stream = stream.makeSubStream(pos, length, dict); if (cipherTransform) diff --git a/src/stream.js b/src/stream.js index 6320c6fc0..b01075840 100644 --- a/src/stream.js +++ b/src/stream.js @@ -57,6 +57,11 @@ var Stream = (function StreamClosure() { this.pos = end; return bytes.subarray(pos, end); }, + peekBytes: function Stream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, lookChar: function Stream_lookChar() { if (this.pos >= this.end) return null; @@ -161,6 +166,11 @@ var DecodeStream = (function DecodeStreamClosure() { this.pos = end; return this.buffer.subarray(pos, end); }, + peekBytes: function DecodeStream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, lookChar: function DecodeStream_lookChar() { var pos = this.pos; while (this.bufferLength <= pos) {