Browse Source

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>
v7.x
Tarjei Husøy 8 years ago
committed by Anna Henningsen
parent
commit
c775514e56
No known key found for this signature in database GPG Key ID: D8B9F5AEAE84E4CF
  1. 14
      src/node_zlib.cc
  2. 14
      test/parallel/test-zlib-dictionary-fail.js
  3. 59
      test/parallel/test-zlib-dictionary.js

14
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;
}

14
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]));
}

59
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();

Loading…
Cancel
Save