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 <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
4019c321d4
commit
c775514e56
@ -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;
|
||||
}
|
||||
|
@ -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]));
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user