Skip to content

Commit 7bc5151

Browse files
anandsureshBridgeAR
authored andcommitted
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: #19686 Reviewed-By: Richard Lau <riclau@uk.ibm.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
1 parent a6db640 commit 7bc5151

File tree

3 files changed

+56
-5
lines changed

3 files changed

+56
-5
lines changed

lib/zlib.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,19 @@ function Zlib(opts, mode) {
251251
opts.finishFlush, 'options.finishFlush',
252252
Z_NO_FLUSH, Z_BLOCK, Z_FINISH);
253253

254-
windowBits = checkRangesOrGetDefault(
255-
opts.windowBits, 'options.windowBits',
256-
Z_MIN_WINDOWBITS, Z_MAX_WINDOWBITS, Z_DEFAULT_WINDOWBITS);
254+
// windowBits is special. On the compression side, 0 is an invalid value.
255+
// But on the decompression side, a value of 0 for windowBits tells zlib
256+
// to use the window size in the zlib header of the compressed stream.
257+
if ((opts.windowBits == null || opts.windowBits === 0) &&
258+
(mode === INFLATE ||
259+
mode === GUNZIP ||
260+
mode === UNZIP)) {
261+
windowBits = 0;
262+
} else {
263+
windowBits = checkRangesOrGetDefault(
264+
opts.windowBits, 'options.windowBits',
265+
Z_MIN_WINDOWBITS, Z_MAX_WINDOWBITS, Z_DEFAULT_WINDOWBITS);
266+
}
257267

258268
level = checkRangesOrGetDefault(
259269
opts.level, 'options.level',

src/node_zlib.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -438,9 +438,17 @@ class ZCtx : public AsyncWrap {
438438
ZCtx* ctx;
439439
ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder());
440440

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

445453
int level = args[1]->Int32Value();
446454
CHECK((level >= Z_MIN_LEVEL && level <= Z_MAX_LEVEL) &&
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const zlib = require('zlib');
6+
7+
8+
// windowBits is a special case in zlib. On the compression side, 0 is invalid.
9+
// On the decompression side, it indicates that zlib should use the value from
10+
// the header of the compressed stream.
11+
{
12+
const inflate = zlib.createInflate({ windowBits: 0 });
13+
assert(inflate instanceof zlib.Inflate);
14+
}
15+
16+
{
17+
const gunzip = zlib.createGunzip({ windowBits: 0 });
18+
assert(gunzip instanceof zlib.Gunzip);
19+
}
20+
21+
{
22+
const unzip = zlib.createUnzip({ windowBits: 0 });
23+
assert(unzip instanceof zlib.Unzip);
24+
}
25+
26+
{
27+
common.expectsError(() => zlib.createGzip({ windowBits: 0 }), {
28+
code: 'ERR_OUT_OF_RANGE',
29+
type: RangeError,
30+
message: 'The value of "options.windowBits" is out of range. ' +
31+
'It must be >= 8 and <= 15. Received 0'
32+
});
33+
}

0 commit comments

Comments
 (0)