From 15474951a5c67e53d6c0077fec6c2c05c82de627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tarjei=20Hus=C3=B8y?= Date: Tue, 20 Sep 2016 11:43:07 -0700 Subject: [PATCH] zlib: fix raw inflate with custom dictionary Moves inflateSetDictionary right after inflateInit2 when mode is INFLATERAW, since without the wrapper in appears zlib won't return Z_NEED_DICT as it would otherwise, and will thus attempt inflating without the dictionary, leading to an error. Fixes: https://github.com/nodejs/node/issues/8507 PR-URL: https://github.com/nodejs/node/pull/8512 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell --- src/node_zlib.cc | 14 ++++- test/parallel/test-zlib-dictionary-fail.js | 14 +++++ test/parallel/test-zlib-dictionary.js | 59 ++++++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/src/node_zlib.cc b/src/node_zlib.cc index 8fb638f7faba4c..2e62fb4160817a 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 52f295157b7e4f..822ca1f02812da 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 2f3fc23a92d684..1636062d48baa2 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();