Make sure Pako always has enough room
Previously, we used a fixed chunkSize of 100KiB for Pako's output buffer. Using a hardcoded size caused issues, since Pako would assume we wanted to use multiple chunks, and we didn't deal with this. Now, `Inflator#inflate()` takes a new `expected` argument, which indicates the expected output size. If this is bigger than the current chunkSize, Inflator allocates a new output buffer that's big enough to hold the output. Fixes #531
This commit is contained in:
parent
40b35fa20d
commit
c802d93189
|
@ -2,4 +2,4 @@ Rebuilding inflator.js
|
||||||
|
|
||||||
- Download pako from npm
|
- Download pako from npm
|
||||||
- Install browserify using npm
|
- Install browserify using npm
|
||||||
- browserify utils/inflator.partial.js -o include/inflator.js
|
- browserify utils/inflator.partial.js -o include/inflator.js -s inflator
|
||||||
|
|
|
@ -234,7 +234,8 @@ module.exports = function inflate_fast(strm, start) {
|
||||||
var wsize; /* window size or zero if not using window */
|
var wsize; /* window size or zero if not using window */
|
||||||
var whave; /* valid bytes in the window */
|
var whave; /* valid bytes in the window */
|
||||||
var wnext; /* window write index */
|
var wnext; /* window write index */
|
||||||
var window; /* allocated sliding window, if wsize != 0 */
|
// Use `s_window` instead `window`, avoid conflict with instrumentation tools
|
||||||
|
var s_window; /* allocated sliding window, if wsize != 0 */
|
||||||
var hold; /* local strm.hold */
|
var hold; /* local strm.hold */
|
||||||
var bits; /* local strm.bits */
|
var bits; /* local strm.bits */
|
||||||
var lcode; /* local strm.lencode */
|
var lcode; /* local strm.lencode */
|
||||||
|
@ -268,7 +269,7 @@ module.exports = function inflate_fast(strm, start) {
|
||||||
wsize = state.wsize;
|
wsize = state.wsize;
|
||||||
whave = state.whave;
|
whave = state.whave;
|
||||||
wnext = state.wnext;
|
wnext = state.wnext;
|
||||||
window = state.window;
|
s_window = state.window;
|
||||||
hold = state.hold;
|
hold = state.hold;
|
||||||
bits = state.bits;
|
bits = state.bits;
|
||||||
lcode = state.lencode;
|
lcode = state.lencode;
|
||||||
|
@ -386,13 +387,13 @@ module.exports = function inflate_fast(strm, start) {
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
from = 0; // window index
|
from = 0; // window index
|
||||||
from_source = window;
|
from_source = s_window;
|
||||||
if (wnext === 0) { /* very common case */
|
if (wnext === 0) { /* very common case */
|
||||||
from += wsize - op;
|
from += wsize - op;
|
||||||
if (op < len) { /* some from window */
|
if (op < len) { /* some from window */
|
||||||
len -= op;
|
len -= op;
|
||||||
do {
|
do {
|
||||||
output[_out++] = window[from++];
|
output[_out++] = s_window[from++];
|
||||||
} while (--op);
|
} while (--op);
|
||||||
from = _out - dist; /* rest from output */
|
from = _out - dist; /* rest from output */
|
||||||
from_source = output;
|
from_source = output;
|
||||||
|
@ -404,14 +405,14 @@ module.exports = function inflate_fast(strm, start) {
|
||||||
if (op < len) { /* some from end of window */
|
if (op < len) { /* some from end of window */
|
||||||
len -= op;
|
len -= op;
|
||||||
do {
|
do {
|
||||||
output[_out++] = window[from++];
|
output[_out++] = s_window[from++];
|
||||||
} while (--op);
|
} while (--op);
|
||||||
from = 0;
|
from = 0;
|
||||||
if (wnext < len) { /* some from start of window */
|
if (wnext < len) { /* some from start of window */
|
||||||
op = wnext;
|
op = wnext;
|
||||||
len -= op;
|
len -= op;
|
||||||
do {
|
do {
|
||||||
output[_out++] = window[from++];
|
output[_out++] = s_window[from++];
|
||||||
} while (--op);
|
} while (--op);
|
||||||
from = _out - dist; /* rest from output */
|
from = _out - dist; /* rest from output */
|
||||||
from_source = output;
|
from_source = output;
|
||||||
|
@ -423,7 +424,7 @@ module.exports = function inflate_fast(strm, start) {
|
||||||
if (op < len) { /* some from window */
|
if (op < len) { /* some from window */
|
||||||
len -= op;
|
len -= op;
|
||||||
do {
|
do {
|
||||||
output[_out++] = window[from++];
|
output[_out++] = s_window[from++];
|
||||||
} while (--op);
|
} while (--op);
|
||||||
from = _out - dist; /* rest from output */
|
from = _out - dist; /* rest from output */
|
||||||
from_source = output;
|
from_source = output;
|
||||||
|
@ -2371,9 +2372,9 @@ function ZStream() {
|
||||||
|
|
||||||
module.exports = ZStream;
|
module.exports = ZStream;
|
||||||
|
|
||||||
},{}],"/partial_inflator.js":[function(require,module,exports){
|
},{}],8:[function(require,module,exports){
|
||||||
var zlib = require('./lib/zlib/inflate.js');
|
var zlib = require('../node_modules/pako/lib/zlib/inflate.js');
|
||||||
var ZStream = require('./lib/zlib/zstream.js');
|
var ZStream = require('../node_modules/pako/lib/zlib/zstream.js');
|
||||||
|
|
||||||
var Inflate = function () {
|
var Inflate = function () {
|
||||||
this.strm = new ZStream();
|
this.strm = new ZStream();
|
||||||
|
@ -2385,12 +2386,20 @@ var Inflate = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
Inflate.prototype = {
|
Inflate.prototype = {
|
||||||
inflate: function (data, flush) {
|
inflate: function (data, flush, expected) {
|
||||||
this.strm.input = data;
|
this.strm.input = data;
|
||||||
this.strm.avail_in = this.strm.input.length;
|
this.strm.avail_in = this.strm.input.length;
|
||||||
this.strm.next_in = 0;
|
this.strm.next_in = 0;
|
||||||
this.strm.next_out = 0;
|
this.strm.next_out = 0;
|
||||||
|
|
||||||
|
// resize our output buffer if it's too small
|
||||||
|
// (we could just use multiple chunks, but that would cause an extra
|
||||||
|
// allocation each time to flatten the chunks)
|
||||||
|
if (expected > this.chunkSize) {
|
||||||
|
this.chunkSize = expected;
|
||||||
|
this.strm.output = new Uint8Array(this.chunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
this.strm.avail_out = this.chunkSize;
|
this.strm.avail_out = this.chunkSize;
|
||||||
|
|
||||||
zlib.inflate(this.strm, flush);
|
zlib.inflate(this.strm, flush);
|
||||||
|
@ -2405,5 +2414,5 @@ Inflate.prototype = {
|
||||||
|
|
||||||
module.exports = {Inflate: Inflate};
|
module.exports = {Inflate: Inflate};
|
||||||
|
|
||||||
},{"./lib/zlib/inflate.js":5,"./lib/zlib/zstream.js":7}]},{},[])("/partial_inflator.js")
|
},{"../node_modules/pako/lib/zlib/inflate.js":5,"../node_modules/pako/lib/zlib/zstream.js":7}]},{},[8])(8)
|
||||||
});
|
});
|
|
@ -1688,16 +1688,17 @@ var RFB;
|
||||||
|
|
||||||
var resetStreams = 0;
|
var resetStreams = 0;
|
||||||
var streamId = -1;
|
var streamId = -1;
|
||||||
var decompress = function (data) {
|
var decompress = function (data, expected) {
|
||||||
for (var i = 0; i < 4; i++) {
|
for (var i = 0; i < 4; i++) {
|
||||||
if ((resetStreams >> i) & 1) {
|
if ((resetStreams >> i) & 1) {
|
||||||
this._FBU.zlibs[i].reset();
|
this._FBU.zlibs[i].reset();
|
||||||
|
console.debug('RESET!');
|
||||||
Util.Info("Reset zlib stream " + i);
|
Util.Info("Reset zlib stream " + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//var uncompressed = this._FBU.zlibs[streamId].uncompress(data, 0);
|
//var uncompressed = this._FBU.zlibs[streamId].uncompress(data, 0);
|
||||||
var uncompressed = this._FBU.zlibs[streamId].inflate(data, true);
|
var uncompressed = this._FBU.zlibs[streamId].inflate(data, true, expected);
|
||||||
/*if (uncompressed.status !== 0) {
|
/*if (uncompressed.status !== 0) {
|
||||||
Util.Error("Invalid data in zlib stream");
|
Util.Error("Invalid data in zlib stream");
|
||||||
}*/
|
}*/
|
||||||
|
@ -1830,7 +1831,7 @@ var RFB;
|
||||||
if (raw) {
|
if (raw) {
|
||||||
data = this._sock.rQshiftBytes(cl_data);
|
data = this._sock.rQshiftBytes(cl_data);
|
||||||
} else {
|
} else {
|
||||||
data = decompress(this._sock.rQshiftBytes(cl_data));
|
data = decompress(this._sock.rQshiftBytes(cl_data), rowSize * this._FBU.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert indexed (palette based) image data to RGB
|
// Convert indexed (palette based) image data to RGB
|
||||||
|
@ -1879,7 +1880,7 @@ var RFB;
|
||||||
if (raw) {
|
if (raw) {
|
||||||
data = this._sock.rQshiftBytes(cl_data);
|
data = this._sock.rQshiftBytes(cl_data);
|
||||||
} else {
|
} else {
|
||||||
data = decompress(this._sock.rQshiftBytes(cl_data));
|
data = decompress(this._sock.rQshiftBytes(cl_data), uncompressedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._display.blitRgbImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, data, 0, false);
|
this._display.blitRgbImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, data, 0, false);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
var zlib = require('./lib/zlib/inflate.js');
|
var zlib = require('../node_modules/pako/lib/zlib/inflate.js');
|
||||||
var ZStream = require('./lib/zlib/zstream.js');
|
var ZStream = require('../node_modules/pako/lib/zlib/zstream.js');
|
||||||
|
|
||||||
var Inflate = function () {
|
var Inflate = function () {
|
||||||
this.strm = new ZStream();
|
this.strm = new ZStream();
|
||||||
|
@ -11,12 +11,20 @@ var Inflate = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
Inflate.prototype = {
|
Inflate.prototype = {
|
||||||
inflate: function (data, flush) {
|
inflate: function (data, flush, expected) {
|
||||||
this.strm.input = data;
|
this.strm.input = data;
|
||||||
this.strm.avail_in = this.strm.input.length;
|
this.strm.avail_in = this.strm.input.length;
|
||||||
this.strm.next_in = 0;
|
this.strm.next_in = 0;
|
||||||
this.strm.next_out = 0;
|
this.strm.next_out = 0;
|
||||||
|
|
||||||
|
// resize our output buffer if it's too small
|
||||||
|
// (we could just use multiple chunks, but that would cause an extra
|
||||||
|
// allocation each time to flatten the chunks)
|
||||||
|
if (expected > this.chunkSize) {
|
||||||
|
this.chunkSize = expected;
|
||||||
|
this.strm.output = new Uint8Array(this.chunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
this.strm.avail_out = this.chunkSize;
|
this.strm.avail_out = this.chunkSize;
|
||||||
|
|
||||||
zlib.inflate(this.strm, flush);
|
zlib.inflate(this.strm, flush);
|
||||||
|
|
Loading…
Reference in New Issue