diff --git a/src/fonts.js b/src/fonts.js index 0f9b6f9d0..2884dcb2e 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -3321,7 +3321,9 @@ var Type2CFF = (function Type2CFFClosure() { parse: function cff_parse() { var header = this.parseHeader(); var properties = this.properties; + var nameIndex = this.parseIndex(header.endPos); + this.sanitizeName(nameIndex); var dictIndex = this.parseIndex(nameIndex.endPos); if (dictIndex.length != 1) @@ -3690,6 +3692,39 @@ var Type2CFF = (function Type2CFFClosure() { } return dict; }, + sanitizeName: function cff_sanitizeName(nameIndex) { + // There should really only be one font, but loop to make sure. + for (var i = 0, ii = nameIndex.length; i < ii; ++i) { + var data = nameIndex.get(i).data; + var length = data.length; + if (length > 127) + warn('Font had name longer than 127 chars, will be rejected.'); + // Only certain chars are permitted in the font name. + for (var j = 0; j < length; ++j) { + var c = data[j]; + if (j === 0 && c === 0) + continue; + if (c < 33 || c > 126) { + data[j] = 95; + continue; + } + switch (c) { + case 91: // [ + case 93: // ] + case 40: // ( + case 41: // ) + case 123: // { + case 125: // } + case 60: // < + case 62: // > + case 47: // / + case 37: // % + data[j] = 95; + break; + } + } + } + }, getStrings: function cff_getStrings(stringIndex) { function bytesToString(bytesArray) { var str = ''; diff --git a/src/stream.js b/src/stream.js index fc163171f..f76a07b4c 100644 --- a/src/stream.js +++ b/src/stream.js @@ -623,7 +623,6 @@ var PredictorStream = (function PredictorStreamClosure() { var bufferLength = this.bufferLength; var buffer = this.ensureBuffer(bufferLength + rowBytes); - var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes); var bits = this.bits; var colors = this.colors; @@ -632,6 +631,7 @@ var PredictorStream = (function PredictorStreamClosure() { var inbuf = 0, outbuf = 0; var inbits = 0, outbits = 0; + var pos = bufferLength; if (bits === 1) { for (var i = 0; i < rowBytes; ++i) { @@ -639,19 +639,21 @@ var PredictorStream = (function PredictorStreamClosure() { inbuf = (inbuf << 8) | c; // bitwise addition is exclusive or // first shift inbuf and then add - currentRow[i] = (c ^ (inbuf >> colors)) & 0xFF; + buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF; // truncate inbuf (assumes colors < 16) inbuf &= 0xFFFF; } } else if (bits === 8) { for (var i = 0; i < colors; ++i) - currentRow[i] = rawBytes[i]; - for (; i < rowBytes; ++i) - currentRow[i] = currentRow[i - colors] + rawBytes[i]; + buffer[pos++] = rawBytes[i]; + for (; i < rowBytes; ++i) { + buffer[pos] = buffer[pos - colors] + rawBytes[i]; + pos++; + } } else { var compArray = new Uint8Array(colors + 1); var bitMask = (1 << bits) - 1; - var j = 0, k = 0; + var j = 0, k = bufferLength; var columns = this.columns; for (var i = 0; i < columns; ++i) { for (var kk = 0; kk < colors; ++kk) { @@ -665,13 +667,13 @@ var PredictorStream = (function PredictorStreamClosure() { outbuf = (outbuf << bits) | compArray[kk]; outbits += bits; if (outbits >= 8) { - currentRow[k++] = (outbuf >> (outbits - 8)) & 0xFF; + buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF; outbits -= 8; } } } if (outbits > 0) { - currentRow[k++] = (outbuf << (8 - outbits)) + + buffer[k++] = (outbuf << (8 - outbits)) + (inbuf & ((1 << (8 - outbits)) - 1)); } } @@ -690,32 +692,35 @@ var PredictorStream = (function PredictorStreamClosure() { var bufferLength = this.bufferLength; var buffer = this.ensureBuffer(bufferLength + rowBytes); - var currentRow = buffer.subarray(bufferLength, bufferLength + rowBytes); var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength); if (prevRow.length == 0) prevRow = new Uint8Array(rowBytes); + var j = bufferLength; switch (predictor) { case 0: for (var i = 0; i < rowBytes; ++i) - currentRow[i] = rawBytes[i]; + buffer[j++] = rawBytes[i]; break; case 1: for (var i = 0; i < pixBytes; ++i) - currentRow[i] = rawBytes[i]; - for (; i < rowBytes; ++i) - currentRow[i] = (currentRow[i - pixBytes] + rawBytes[i]) & 0xFF; + buffer[j++] = rawBytes[i]; + for (; i < rowBytes; ++i) { + buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF; + j++; + } break; case 2: for (var i = 0; i < rowBytes; ++i) - currentRow[i] = (prevRow[i] + rawBytes[i]) & 0xFF; + buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF; break; case 3: for (var i = 0; i < pixBytes; ++i) - currentRow[i] = (prevRow[i] >> 1) + rawBytes[i]; + buffer[j++] = (prevRow[i] >> 1) + rawBytes[i]; for (; i < rowBytes; ++i) { - currentRow[i] = (((prevRow[i] + currentRow[i - pixBytes]) >> 1) + + buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) + rawBytes[i]) & 0xFF; + j++; } break; case 4: @@ -724,12 +729,12 @@ var PredictorStream = (function PredictorStreamClosure() { for (var i = 0; i < pixBytes; ++i) { var up = prevRow[i]; var c = rawBytes[i]; - currentRow[i] = up + c; + buffer[j++] = up + c; } for (; i < rowBytes; ++i) { var up = prevRow[i]; var upLeft = prevRow[i - pixBytes]; - var left = currentRow[i - pixBytes]; + var left = buffer[j - pixBytes]; var p = left + up - upLeft; var pa = p - left; @@ -744,11 +749,11 @@ var PredictorStream = (function PredictorStreamClosure() { var c = rawBytes[i]; if (pa <= pb && pa <= pc) - currentRow[i] = left + c; + buffer[j++] = left + c; else if (pb <= pc) - currentRow[i] = up + c; + buffer[j++] = up + c; else - currentRow[i] = upLeft + c; + buffer[j++] = upLeft + c; } break; default: diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index e0926492b..9460cfbec 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -24,3 +24,4 @@ !type4psfunc.pdf !S2.pdf !zerowidthline.pdf +!issue925.pdf diff --git a/test/pdfs/issue925.pdf b/test/pdfs/issue925.pdf new file mode 100755 index 000000000..16329cbef Binary files /dev/null and b/test/pdfs/issue925.pdf differ diff --git a/test/resources/firefox/extensions/special-powers@mozilla.org/install.rdf b/test/resources/firefox/extensions/special-powers@mozilla.org/install.rdf index db8de988e..490d4ddaf 100644 --- a/test/resources/firefox/extensions/special-powers@mozilla.org/install.rdf +++ b/test/resources/firefox/extensions/special-powers@mozilla.org/install.rdf @@ -14,7 +14,7 @@ toolkit@mozilla.org 3.0 - 7.0a1 + 13.0a1 diff --git a/test/test_manifest.json b/test/test_manifest.json index e09f16da9..e9aebdc90 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -460,6 +460,13 @@ "link": true, "type": "eq" }, + { "id": "issue925", + "file": "pdfs/issue925.pdf", + "md5": "f58fe943090aff89dcc8e771bc0db4c2", + "rounds": 1, + "link": true, + "type": "eq" + }, { "id": "issue1133", "file": "pdfs/issue1133.pdf", "md5": "d1b61580cb100e3df93d33703af1773a", diff --git a/web/viewer.js b/web/viewer.js index 27e79a31d..816f14ffe 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -321,7 +321,8 @@ var PDFView = { if (pageNumber) { var pdfOpenParams = PDFView.getAnchorUrl('#page=' + pageNumber); var destKind = dest[1]; - if ('name' in destKind && destKind.name == 'XYZ') { + if (typeof destKind === 'object' && 'name' in destKind && + destKind.name == 'XYZ') { var scale = (dest[4] || this.currentScale); pdfOpenParams += '&zoom=' + (scale * 100); if (dest[2] || dest[3]) { @@ -621,10 +622,13 @@ var PDFView = { // Helper function to parse query string (e.g. ?param1=value&parm2=...). parseQueryString: function pdfViewParseQueryString(query) { - var params = query.split('&'); - for (var i = 0; i < params.length; i++) { - var param = params[i].split('='); - params[unescape(param[0])] = unescape(param[1]); + var parts = query.split('&'); + var params = {}; + for (var i = 0, ii = parts.length; i < parts.length; ++i) { + var param = parts[i].split('='); + var key = param[0]; + var value = param.length > 1 ? param[1] : null; + params[unescape(key)] = unescape(value); } return params; }