diff --git a/lib/zlib.js b/lib/zlib.js index 2d37b72a3c8b20..67bdcaff64bed6 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -5,6 +5,9 @@ const Transform = require('_stream_transform'); const binding = process.binding('zlib'); const util = require('util'); const assert = require('assert').ok; +const kMaxLength = process.binding('smalloc').kMaxLength; +const kRangeErrorMessage = 'Cannot create final Buffer. ' + + 'It would be larger than 0x' + kMaxLength.toString(16) + ' bytes.'; // zlib doesn't provide these, so kludge them in following the same // const naming scheme zlib uses. @@ -210,10 +213,18 @@ function zlibBuffer(engine, buffer, callback) { } function onEnd() { - var buf = Buffer.concat(buffers, nread); + var buf; + var err = null; + + if (nread >= kMaxLength) { + err = new RangeError(kRangeErrorMessage); + } else { + buf = Buffer.concat(buffers, nread); + } + buffers = []; - callback(null, buf); engine.close(); + callback(err, buf); } } @@ -524,6 +535,11 @@ Zlib.prototype._processChunk = function(chunk, flushFlag, cb) { throw error; } + if (nread >= kMaxLength) { + this.close(); + throw new RangeError(kRangeErrorMessage); + } + var buf = Buffer.concat(buffers, nread); this.close(); diff --git a/test/parallel/test-regress-GH-io-1811.js b/test/parallel/test-regress-GH-io-1811.js new file mode 100644 index 00000000000000..2ef8ff8c090aa4 --- /dev/null +++ b/test/parallel/test-regress-GH-io-1811.js @@ -0,0 +1,22 @@ +'use strict'; + +const assert = require('assert'); + +// Change kMaxLength for zlib to trigger the error +// without having to allocate 1GB of buffers +const smalloc = process.binding('smalloc'); +smalloc.kMaxLength = 128; +const zlib = require('zlib'); +smalloc.kMaxLength = 0x3fffffff; + +const encoded = new Buffer('H4sIAAAAAAAAA0tMHFgAAIw2K/GAAAAA', 'base64'); + +// Async +zlib.gunzip(encoded, function(err) { + assert.ok(err instanceof RangeError); +}); + +// Sync +assert.throws(function() { + zlib.gunzipSync(encoded); +}, RangeError);