diff --git a/src/node_zlib.cc b/src/node_zlib.cc index 0b8f1e06f513b2..304fbf72fed44f 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -238,8 +238,11 @@ class ZCtx : public AsyncWrap { case INFLATERAW: ctx->err_ = inflate(&ctx->strm_, ctx->flush_); - // If data was encoded with dictionary - if (ctx->err_ == Z_NEED_DICT && ctx->dictionary_ != nullptr) { + // If data was encoded with dictionary (INFLATERAW will have it set in + // SetDictionary, don't repeat that here) + if (ctx->mode_ != INFLATERAW && + ctx->err_ == Z_NEED_DICT && + ctx->dictionary_ != nullptr) { // Load it ctx->err_ = inflateSetDictionary(&ctx->strm_, ctx->dictionary_, @@ -491,6 +494,13 @@ class ZCtx : public AsyncWrap { ctx->dictionary_, ctx->dictionary_len_); break; + case INFLATERAW: + // The other inflate cases will have the dictionary set when inflate() + // returns Z_NEED_DICT in Process() + ctx->err_ = inflateSetDictionary(&ctx->strm_, + ctx->dictionary_, + ctx->dictionary_len_); + break; default: break; } diff --git a/test/parallel/test-zlib-dictionary-fail.js b/test/parallel/test-zlib-dictionary-fail.js index b4a344ceef5bb9..01d467aab80806 100644 --- a/test/parallel/test-zlib-dictionary-fail.js +++ b/test/parallel/test-zlib-dictionary-fail.js @@ -26,3 +26,17 @@ var zlib = require('zlib'); // String "test" encoded with dictionary "dict". stream.write(Buffer([0x78, 0xBB, 0x04, 0x09, 0x01, 0xA5])); })(); + +// Should raise an error, not trigger an assertion in src/node_zlib.cc +(function() { + var stream = zlib.createInflateRaw({ dictionary: Buffer('fail') }); + + stream.on('error', common.mustCall(function(err) { + // It's not possible to separate invalid dict and invalid data when using + // the raw format + assert(/invalid/.test(err.message)); + })); + + // String "test" encoded with dictionary "dict". + stream.write(Buffer([0x78, 0xBB, 0x04, 0x09, 0x01, 0xA5])); +})(); diff --git a/test/parallel/test-zlib-dictionary.js b/test/parallel/test-zlib-dictionary.js index f8ce5bfbe87df4..51cd3cc036c2ea 100644 --- a/test/parallel/test-zlib-dictionary.js +++ b/test/parallel/test-zlib-dictionary.js @@ -1,7 +1,7 @@ 'use strict'; // test compression/decompression with dictionary -require('../common'); +const common = require('../common'); const assert = require('assert'); const zlib = require('zlib'); @@ -69,6 +69,66 @@ function run(num) { } run(1); +function rawDictionaryTest() { + let output = ''; + const deflate = zlib.createDeflateRaw({ dictionary: spdyDict }); + const inflate = zlib.createInflateRaw({ dictionary: spdyDict }); + + deflate.on('data', function(chunk) { + inflate.write(chunk); + }); + + inflate.on('data', function(chunk) { + output += chunk; + }); + + deflate.on('end', function() { + inflate.end(); + }); + + inflate.on('end', common.mustCall(function() { + assert.equal(input, output); + })); + + deflate.write(input); + deflate.end(); +} + +function deflateRawResetDictionaryTest() { + let doneReset = false; + let output = ''; + const deflate = zlib.createDeflateRaw({ dictionary: spdyDict }); + const inflate = zlib.createInflateRaw({ dictionary: spdyDict }); + + deflate.on('data', function(chunk) { + if (doneReset) + inflate.write(chunk); + }); + + inflate.on('data', function(chunk) { + output += chunk; + }); + + deflate.on('end', function() { + inflate.end(); + }); + + inflate.on('end', common.mustCall(function() { + assert.equal(input, output); + })); + + deflate.write(input); + deflate.flush(function() { + deflate.reset(); + doneReset = true; + deflate.write(input); + deflate.end(); + }); +} + +rawDictionaryTest(); +deflateRawResetDictionaryTest(); + process.on('exit', function() { assert.equal(called, 2); });