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.
v4.x
Tarjei Husøy 8 years ago
committed by Myles Borins
parent
commit
9a02414a29
  1. 14
      src/node_zlib.cc
  2. 14
      test/parallel/test-zlib-dictionary-fail.js
  3. 62
      test/parallel/test-zlib-dictionary.js

14
src/node_zlib.cc

@ -238,8 +238,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_,
@ -491,6 +494,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 @@ var zlib = require('zlib');
// String "test" encoded with dictionary "dict".
stream.write(Buffer([0x78, 0xBB, 0x04, 0x09, 0x01, 0xA5]));
})();
// Should raise an error, not trigger an assertion in src/node_zlib.cc
(function() {
var stream = zlib.createInflateRaw({ dictionary: Buffer('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([0x78, 0xBB, 0x04, 0x09, 0x01, 0xA5]));
})();

62
test/parallel/test-zlib-dictionary.js

@ -1,7 +1,7 @@
'use strict';
// test compression/decompression with dictionary
require('../common');
const common = require('../common');
const assert = require('assert');
const zlib = require('zlib');
@ -69,6 +69,66 @@ function run(num) {
}
run(1);
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', common.mustCall(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', common.mustCall(function() {
assert.equal(input, output);
}));
deflate.write(input);
deflate.flush(function() {
deflate.reset();
doneReset = true;
deflate.write(input);
deflate.end();
});
}
rawDictionaryTest();
deflateRawResetDictionaryTest();
process.on('exit', function() {
assert.equal(called, 2);
});

Loading…
Cancel
Save