diff --git a/src/node_zlib.cc b/src/node_zlib.cc index 09910e79eb..0b85e6a1d6 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -282,8 +282,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_, @@ -552,6 +555,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 52f295157b..822ca1f028 100644 --- a/test/parallel/test-zlib-dictionary-fail.js +++ b/test/parallel/test-zlib-dictionary-fail.js @@ -26,3 +26,17 @@ const zlib = require('zlib'); // String "test" encoded with dictionary "dict". stream.write(Buffer.from([0x78, 0xBB, 0x04, 0x09, 0x01, 0xA5])); } + +// Should raise an error, not trigger an assertion in src/node_zlib.cc +{ + const stream = zlib.createInflateRaw({ dictionary: Buffer.from('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.from([0x78, 0xBB, 0x04, 0x09, 0x01, 0xA5])); +} diff --git a/test/parallel/test-zlib-dictionary.js b/test/parallel/test-zlib-dictionary.js index 2f3fc23a92..1636062d48 100644 --- a/test/parallel/test-zlib-dictionary.js +++ b/test/parallel/test-zlib-dictionary.js @@ -85,5 +85,64 @@ function deflateResetDictionaryTest() { }); } +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', 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', function() { + assert.equal(input, output); + }); + + deflate.write(input); + deflate.flush(function() { + deflate.reset(); + doneReset = true; + deflate.write(input); + deflate.end(); + }); +} + basicDictionaryTest(); deflateResetDictionaryTest(); +rawDictionaryTest(); +deflateRawResetDictionaryTest();