zlib: fix windowBits validation to allow 0 for decompression mode

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: https://github.com/nodejs/node/pull/19686
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
Anand Suresh 2018-03-29 15:07:44 -07:00 committed by Ruben Bridgewater
parent a6db6404ff
commit 7bc5151d5e
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
3 changed files with 56 additions and 5 deletions

View File

@ -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',

View File

@ -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) &&

View File

@ -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'
});
}