Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zlib: gracefully set windowBits from 8 to 9 #16511

Merged
merged 2 commits into from
Oct 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions doc/api/zlib.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,9 +458,12 @@ added: v0.5.8

Creates and returns a new [DeflateRaw][] object with the given [options][].

*Note*: The zlib library rejects requests for 256-byte windows (i.e.,
`{ windowBits: 8 }` in `options`). An `Error` will be thrown when creating
a [DeflateRaw][] object with this specific value of the `windowBits` option.
*Note*: An upgrade of zlib from 1.2.8 to 1.2.11 changed behavior when windowBits
is set to 8 for raw deflate streams. zlib would automatically set windowBits
to 9 if was initially set to 8. Newer versions of zlib will throw an exception,
so Node.js restored the original behavior of upgrading a value of 8 to 9,
since passing `windowBits = 9` to zlib actually results in a compressed stream
that effectively uses an 8-bit window only.

## zlib.createGunzip([options])
<!-- YAML
Expand Down
1 change: 1 addition & 0 deletions lib/zlib.js
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ function Gunzip(opts) {
inherits(Gunzip, Zlib);

function DeflateRaw(opts) {
if (opts && opts.windowBits === 8) opts.windowBits = 9;
if (!(this instanceof DeflateRaw))
return new DeflateRaw(opts);
Zlib.call(this, opts, DEFLATERAW);
Expand Down
17 changes: 0 additions & 17 deletions test/parallel/test-zlib-failed-init.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,6 @@ const common = require('../common');
const assert = require('assert');
const zlib = require('zlib');

// For raw deflate encoding, requests for 256-byte windows are rejected as
// invalid by zlib (http://zlib.net/manual.html#Advanced).
// This check was introduced in version 1.2.9 and prior to that there was
// no such rejection which is the reason for the version check below
// (http://zlib.net/ChangeLog.txt).
if (!/^1\.2\.[0-8]$/.test(process.versions.zlib)) {
common.expectsError(
() => zlib.createDeflateRaw({ windowBits: 8 }),
{
code: 'ERR_ZLIB_INITIALIZATION_FAILED',
type: Error,
message: 'Initialization failed'
});
}

// Regression tests for bugs in the validation logic.

common.expectsError(
() => zlib.createGzip({ chunkSize: 0 }),
{
Expand Down
24 changes: 24 additions & 0 deletions test/parallel/test-zlib.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const common = require('../common');
const assert = require('assert');
const zlib = require('zlib');
const stream = require('stream');
const fs = require('fs');
const fixtures = require('../common/fixtures');

let zlibPairs = [
Expand Down Expand Up @@ -150,6 +151,29 @@ class SlowStream extends stream.Stream {
}
}

// windowBits: 8 shouldn't throw
assert.doesNotThrow(() => {
zlib.createDeflateRaw({ windowBits: 8 });
}, 'windowsBits set to 8 should follow legacy zlib behavior');

{
const node = fs.createReadStream(process.execPath);
const raw = [];
const reinflated = [];
node.on('data', (chunk) => raw.push(chunk));

// Usually, the inflate windowBits parameter needs to be at least the
// value of the matching deflate’s windowBits. However, inflate raw with
// windowBits = 8 should be able to handle compressed data from a source
// that does not know about the silent 8-to-9 upgrade of windowBits
// that most versions of zlib/Node perform, and which *still* results in
// a valid 8-bit-window zlib stream.
node.pipe(zlib.createDeflateRaw({ windowBits: 9 }))
.pipe(zlib.createInflateRaw({ windowBits: 8 }))
.on('data', (chunk) => reinflated.push(chunk))
.on('end', common.mustCall(
() => assert(Buffer.concat(raw).equals(Buffer.concat(reinflated)))));
}

// for each of the files, make sure that compressing and
// decompressing results in the same data, for every combination
Expand Down