From df6fd387dfa9c781aa033ce4261a32c86773f35a Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 21 Jun 2013 15:42:55 -0500 Subject: [PATCH 1/6] Bug 879211: ignoring bad document outline reference --- src/obj.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/obj.js b/src/obj.js index 9df41af1c..a106896e5 100644 --- a/src/obj.js +++ b/src/obj.js @@ -244,6 +244,18 @@ var Catalog = (function CatalogClosure() { return shadow(this, 'toplevelPagesDict', pagesObj); }, get documentOutline() { + var obj = null; + try { + obj = this.readDocumentOutline(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn('Unable to read document outline'); + } + return shadow(this, 'documentOutline', obj); + }, + readDocumentOutline: function Catalog_readDocumentOutline() { var xref = this.xref; var obj = this.catDict.get('Outlines'); var root = { items: [] }; @@ -294,8 +306,7 @@ var Catalog = (function CatalogClosure() { } } } - obj = root.items.length > 0 ? root.items : null; - return shadow(this, 'documentOutline', obj); + return root.items.length > 0 ? root.items : null; }, get numPages() { var obj = this.toplevelPagesDict.get('Count'); From 0d229351f305aa6145a9519984c8454f3b2dd607 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 21 Jun 2013 17:35:52 -0500 Subject: [PATCH 2/6] Bug 874851: ignoring bad stream length --- src/parser.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/parser.js b/src/parser.js index a0f6c295e..72747e524 100644 --- a/src/parser.js +++ b/src/parser.js @@ -208,8 +208,9 @@ var Parser = (function ParserClosure() { stream.pos = pos + length; this.shift(); // '>>' this.shift(); // 'stream' - if (!isCmd(this.buf1, 'endstream')) - error('Missing endstream'); + if (!isCmd(this.buf1, 'endstream')) { + warn('Missing endstream'); + } this.shift(); stream = stream.makeSubStream(pos, length, dict); From c3030dee8f3feec53d4ed45bc306a5edc67018c7 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 21 Jun 2013 18:47:10 -0500 Subject: [PATCH 3/6] Bug 861638: ignoring double-EI --- src/evaluator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluator.js b/src/evaluator.js index d30865f82..64500ad9a 100644 --- a/src/evaluator.js +++ b/src/evaluator.js @@ -122,7 +122,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { // Images BI: { fnName: 'beginInlineImage', numArgs: 0, variableArgs: false }, ID: { fnName: 'beginImageData', numArgs: 0, variableArgs: false }, - EI: { fnName: 'endInlineImage', numArgs: 0, variableArgs: false }, + EI: { fnName: 'endInlineImage', numArgs: 1, variableArgs: false }, // XObjects Do: { fnName: 'paintXObject', numArgs: 1, variableArgs: false }, From c3096d98d40006adde546dbd6a0f51d5d793677b Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Sat, 22 Jun 2013 12:06:37 -0500 Subject: [PATCH 4/6] #3248: fixes hp scanner's bad XRef --- src/obj.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/obj.js b/src/obj.js index a106896e5..21204ef42 100644 --- a/src/obj.js +++ b/src/obj.js @@ -587,6 +587,12 @@ var XRef = (function XRefClosure() { delete tableState.entryCount; } + // Per issue 3248: hp scanners generate bad XRef + if (first === 1 && this.entries[1] && this.entries[1].free) { + // shifting the entries + this.entries.shift(); + } + // Sanity check: as per spec, first object must be free if (this.entries[0] && !this.entries[0].free) error('Invalid XRef table: unexpected first object'); From 4d9ee7b53002cc34e42b503db31530deea50c62c Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Sat, 22 Jun 2013 13:21:19 -0500 Subject: [PATCH 5/6] #2098: scanning for stream length when it's incorrect --- src/chunked_stream.js | 6 ++++++ src/parser.js | 41 +++++++++++++++++++++++++++++++++++++++-- src/stream.js | 10 ++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) 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) { From aac0f80aad7fee242df1109f13e261e0b4c5d9e8 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Sat, 22 Jun 2013 14:07:04 -0500 Subject: [PATCH 6/6] #1277: ignoring error for bad "empty" block --- src/stream.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/stream.js b/src/stream.js index b01075840..985514f80 100644 --- a/src/stream.js +++ b/src/stream.js @@ -504,8 +504,11 @@ var FlateStream = (function FlateStreamClosure() { if (typeof (b = bytes[bytesPos++]) == 'undefined') error('Bad block header in flate stream'); check |= (b << 8); - if (check != (~blockLen & 0xffff)) + if (check != (~blockLen & 0xffff) && + (blockLen !== 0 || check !== 0)) { + // Ignoring error for bad "empty" block (see issue 1277) error('Bad uncompressed block length in flate stream'); + } this.codeBuf = 0; this.codeSize = 0;