Skip to content

Commit

Permalink
zlib: fix raw inflate with custom dictionary
Browse files Browse the repository at this point in the history
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: #8507
PR-URL: #8512
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
thusoy authored and Fishrock123 committed Oct 11, 2016
1 parent c98d0c9 commit 1547495
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 2 deletions.
14 changes: 12 additions & 2 deletions src/node_zlib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_,
Expand Down Expand Up @@ -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;
}
Expand Down
14 changes: 14 additions & 0 deletions test/parallel/test-zlib-dictionary-fail.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 59 additions & 0 deletions test/parallel/test-zlib-dictionary.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();

0 comments on commit 1547495

Please sign in to comment.