Skip to content

Commit

Permalink
zlib: fix windowBits validation to allow 0 for decompression mode
Browse files Browse the repository at this point in the history
From the zlib v1.2.11 manual:

> ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
>                                      int  windowBits));
>
> ...
> windowBits can also be zero to request that inflate use the window
> size in the zlib header of the compressed stream.

The current validation of windowBits in zlib.js doesn't check for this
case.

PR-URL: #19686
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
  • Loading branch information
anandsuresh authored and BridgeAR committed Apr 9, 2018
1 parent a6db640 commit 7bc5151
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 5 deletions.
16 changes: 13 additions & 3 deletions lib/zlib.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,19 @@ function Zlib(opts, mode) {
opts.finishFlush, 'options.finishFlush',
Z_NO_FLUSH, Z_BLOCK, Z_FINISH);

windowBits = checkRangesOrGetDefault(
opts.windowBits, 'options.windowBits',
Z_MIN_WINDOWBITS, Z_MAX_WINDOWBITS, Z_DEFAULT_WINDOWBITS);
// windowBits is special. On the compression side, 0 is an invalid value.
// But on the decompression side, a value of 0 for windowBits tells zlib
// to use the window size in the zlib header of the compressed stream.
if ((opts.windowBits == null || opts.windowBits === 0) &&
(mode === INFLATE ||
mode === GUNZIP ||
mode === UNZIP)) {
windowBits = 0;
} else {
windowBits = checkRangesOrGetDefault(
opts.windowBits, 'options.windowBits',
Z_MIN_WINDOWBITS, Z_MAX_WINDOWBITS, Z_DEFAULT_WINDOWBITS);
}

level = checkRangesOrGetDefault(
opts.level, 'options.level',
Expand Down
12 changes: 10 additions & 2 deletions src/node_zlib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -438,9 +438,17 @@ class ZCtx : public AsyncWrap {
ZCtx* ctx;
ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());

// windowBits is special. On the compression side, 0 is an invalid value.
// But on the decompression side, a value of 0 for windowBits tells zlib
// to use the window size in the zlib header of the compressed stream.
int windowBits = args[0]->Uint32Value();
CHECK((windowBits >= Z_MIN_WINDOWBITS && windowBits <= Z_MAX_WINDOWBITS) &&
"invalid windowBits");
if (!((windowBits == 0) &&
(ctx->mode_ == INFLATE ||
ctx->mode_ == GUNZIP ||
ctx->mode_ == UNZIP))) {
CHECK((windowBits >= Z_MIN_WINDOWBITS &&
windowBits <= Z_MAX_WINDOWBITS) && "invalid windowBits");
}

int level = args[1]->Int32Value();
CHECK((level >= Z_MIN_LEVEL && level <= Z_MAX_LEVEL) &&
Expand Down
33 changes: 33 additions & 0 deletions test/parallel/test-zlib-zero-windowBits.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const zlib = require('zlib');


// windowBits is a special case in zlib. On the compression side, 0 is invalid.
// On the decompression side, it indicates that zlib should use the value from
// the header of the compressed stream.
{
const inflate = zlib.createInflate({ windowBits: 0 });
assert(inflate instanceof zlib.Inflate);
}

{
const gunzip = zlib.createGunzip({ windowBits: 0 });
assert(gunzip instanceof zlib.Gunzip);
}

{
const unzip = zlib.createUnzip({ windowBits: 0 });
assert(unzip instanceof zlib.Unzip);
}

{
common.expectsError(() => zlib.createGzip({ windowBits: 0 }), {
code: 'ERR_OUT_OF_RANGE',
type: RangeError,
message: 'The value of "options.windowBits" is out of range. ' +
'It must be >= 8 and <= 15. Received 0'
});
}

0 comments on commit 7bc5151

Please sign in to comment.