Skip to content

Commit efae43f

Browse files
aqrlnjasnell
authored andcommitted
zlib: fix node crashing on invalid options
This commit fixes the Node process crashing when constructors of classes of the zlib module are given invalid options. * Throw an Error when the zlib library rejects the value of windowBits, instead of crashing with an assertion. * Treat windowBits and memLevel options consistently with other ones and don't crash when non-numeric values are given. * Fix bugs in the validation logic: - Don't conflate 0 and undefined when checking if a field of an options object exists. - Treat NaN and Infinity values the same way as values of invalid types instead of allowing to actually set zlib options to NaN or Infinity. PR-URL: #13098Fixes: #13082 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Sakthipriyan Vairamani <[email protected]>
1 parent b4f6ea0 commit efae43f

File tree

4 files changed

+73
-15
lines changed

4 files changed

+73
-15
lines changed

‎doc/api/zlib.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,10 @@ added: v0.5.8
437437

438438
Returns a new [DeflateRaw][] object with an [options][].
439439

440+
**Note:** The zlib library rejects requests for 256-byte windows (i.e.,
441+
`{windowBits: 8 }` in `options`). An `Error` will be thrown when creating
442+
a [DeflateRaw][] object with this specific value of the `windowBits` option.
443+
440444
## zlib.createGunzip([options])
441445
<!-- YAML
442446
added: v0.5.8

‎lib/zlib.js‎

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -182,37 +182,37 @@ class Zlib extends Transform{
182182
this._finishFlushFlag=opts.finishFlush!==undefined ?
183183
opts.finishFlush : constants.Z_FINISH;
184184

185-
if(opts.chunkSize){
185+
if(opts.chunkSize!==undefined){
186186
if(opts.chunkSize<constants.Z_MIN_CHUNK){
187187
thrownewRangeError('Invalid chunk size: '+opts.chunkSize);
188188
}
189189
}
190190

191-
if(opts.windowBits){
191+
if(opts.windowBits!==undefined){
192192
if(opts.windowBits<constants.Z_MIN_WINDOWBITS||
193193
opts.windowBits>constants.Z_MAX_WINDOWBITS){
194194
thrownewRangeError('Invalid windowBits: '+opts.windowBits);
195195
}
196196
}
197197

198-
if(opts.level){
198+
if(opts.level!==undefined){
199199
if(opts.level<constants.Z_MIN_LEVEL||
200200
opts.level>constants.Z_MAX_LEVEL){
201201
thrownewRangeError('Invalid compression level: '+opts.level);
202202
}
203203
}
204204

205-
if(opts.memLevel){
205+
if(opts.memLevel!==undefined){
206206
if(opts.memLevel<constants.Z_MIN_MEMLEVEL||
207207
opts.memLevel>constants.Z_MAX_MEMLEVEL){
208208
thrownewRangeError('Invalid memLevel: '+opts.memLevel);
209209
}
210210
}
211211

212-
if(opts.strategy&&isInvalidStrategy(opts.strategy))
212+
if(opts.strategy!==undefined&&isInvalidStrategy(opts.strategy))
213213
thrownewTypeError('Invalid strategy: '+opts.strategy);
214214

215-
if(opts.dictionary){
215+
if(opts.dictionary!==undefined){
216216
if(!ArrayBuffer.isView(opts.dictionary)){
217217
thrownewTypeError(
218218
'Invalid dictionary: it should be a Buffer, TypedArray, or DataView');
@@ -224,14 +224,28 @@ class Zlib extends Transform{
224224
this._hadError=false;
225225

226226
varlevel=constants.Z_DEFAULT_COMPRESSION;
227-
if(typeofopts.level==='number')level=opts.level;
227+
if(Number.isFinite(opts.level)){
228+
level=opts.level;
229+
}
228230

229231
varstrategy=constants.Z_DEFAULT_STRATEGY;
230-
if(typeofopts.strategy==='number')strategy=opts.strategy;
232+
if(Number.isFinite(opts.strategy)){
233+
strategy=opts.strategy;
234+
}
235+
236+
varwindowBits=constants.Z_DEFAULT_WINDOWBITS;
237+
if(Number.isFinite(opts.windowBits)){
238+
windowBits=opts.windowBits;
239+
}
240+
241+
varmemLevel=constants.Z_DEFAULT_MEMLEVEL;
242+
if(Number.isFinite(opts.memLevel)){
243+
memLevel=opts.memLevel;
244+
}
231245

232-
this._handle.init(opts.windowBits||constants.Z_DEFAULT_WINDOWBITS,
246+
this._handle.init(windowBits,
233247
level,
234-
opts.memLevel||constants.Z_DEFAULT_MEMLEVEL,
248+
memLevel,
235249
strategy,
236250
opts.dictionary);
237251

‎src/node_zlib.cc‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -551,16 +551,19 @@ class ZCtx : public AsyncWrap{
551551
CHECK(0 && "wtf?");
552552
}
553553

554-
if (ctx->err_ != Z_OK){
555-
ZCtx::Error(ctx, "Init error");
556-
}
557-
558-
559554
ctx->dictionary_ = reinterpret_cast<Bytef *>(dictionary);
560555
ctx->dictionary_len_ = dictionary_len;
561556

562557
ctx->write_in_progress_ = false;
563558
ctx->init_done_ = true;
559+
560+
if (ctx->err_ != Z_OK){
561+
if (dictionary != nullptr){
562+
delete[] dictionary;
563+
ctx->dictionary_ = nullptr;
564+
}
565+
ctx->env()->ThrowError("Init error");
566+
}
564567
}
565568

566569
staticvoidSetDictionary(ZCtx* ctx){
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use strict';
2+
3+
require('../common');
4+
5+
constassert=require('assert');
6+
constzlib=require('zlib');
7+
8+
// For raw deflate encoding, requests for 256-byte windows are rejected as
9+
// invalid by zlib.
10+
// (http://zlib.net/manual.html#Advanced)
11+
assert.throws(()=>{
12+
zlib.createDeflateRaw({windowBits: 8});
13+
},/^Error:Initerror$/);
14+
15+
// Regression tests for bugs in the validation logic.
16+
17+
assert.throws(()=>{
18+
zlib.createGzip({chunkSize: 0});
19+
},/^RangeError:Invalidchunksize:0$/);
20+
21+
assert.throws(()=>{
22+
zlib.createGzip({windowBits: 0});
23+
},/^RangeError:InvalidwindowBits:0$/);
24+
25+
assert.throws(()=>{
26+
zlib.createGzip({memLevel: 0});
27+
},/^RangeError:InvalidmemLevel:0$/);
28+
29+
{
30+
conststream=zlib.createGzip({level: NaN});
31+
assert.strictEqual(stream._level,zlib.constants.Z_DEFAULT_COMPRESSION);
32+
}
33+
34+
{
35+
conststream=zlib.createGzip({strategy: NaN});
36+
assert.strictEqual(stream._strategy,zlib.constants.Z_DEFAULT_STRATEGY);
37+
}

0 commit comments

Comments
(0)