From 01f853cde60e137c11c3f5e3290456a528418720 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 15 Nov 2017 12:13:43 +0100 Subject: [PATCH] zlib: fix decompression of empty data streams add4b0ab8cc0ec6 made the assumption that compressed data would never lead to an empty decompressed stream. Fix that by explicitly checking the number of read bytes. PR-URL: https://github.com/nodejs/node/pull/17042 Fixes: https://github.com/nodejs/node/issues/17041 Refs: https://github.com/nodejs/node/pull/13322 Reviewed-By: Ben Noordhuis Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig Reviewed-By: Evan Lucas Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- lib/zlib.js | 5 +++++ test/parallel/test-zlib-empty-buffer.js | 26 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 test/parallel/test-zlib-empty-buffer.js diff --git a/lib/zlib.js b/lib/zlib.js index 2def716e9b676c..75ee0b50465111 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -95,6 +95,8 @@ function zlibBufferOnEnd() { var err; if (this.nread >= kMaxLength) { err = new errors.RangeError('ERR_BUFFER_TOO_LARGE'); + } else if (this.nread === 0) { + buf = Buffer.alloc(0); } else { var bufs = this.buffers; buf = (bufs.length === 1 ? bufs[0] : Buffer.concat(bufs, this.nread)); @@ -485,6 +487,9 @@ function processChunkSync(self, chunk, flushFlag) { _close(self); + if (nread === 0) + return Buffer.alloc(0); + return (buffers.length === 1 ? buffers[0] : Buffer.concat(buffers, nread)); } diff --git a/test/parallel/test-zlib-empty-buffer.js b/test/parallel/test-zlib-empty-buffer.js new file mode 100644 index 00000000000000..908c89cbbcef2e --- /dev/null +++ b/test/parallel/test-zlib-empty-buffer.js @@ -0,0 +1,26 @@ +'use strict'; +const common = require('../common'); +const zlib = require('zlib'); +const { inspect, promisify } = require('util'); +const assert = require('assert'); +const emptyBuffer = new Buffer(0); + +common.crashOnUnhandledRejection(); + +(async function() { + for (const [ compress, decompress, method ] of [ + [ zlib.deflateRawSync, zlib.inflateRawSync, 'raw sync' ], + [ zlib.deflateSync, zlib.inflateSync, 'deflate sync' ], + [ zlib.gzipSync, zlib.gunzipSync, 'gzip sync' ], + [ promisify(zlib.deflateRaw), promisify(zlib.inflateRaw), 'raw' ], + [ promisify(zlib.deflate), promisify(zlib.inflate), 'deflate' ], + [ promisify(zlib.gzip), promisify(zlib.gunzip), 'gzip' ] + ]) { + const compressed = await compress(emptyBuffer); + const decompressed = await decompress(compressed); + assert.deepStrictEqual( + emptyBuffer, decompressed, + `Expected ${inspect(compressed)} to match ${inspect(decompressed)} ` + + `to match for ${method}`); + } +})();