Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
zlib: fix bugs in the validation logic
  • Loading branch information
aqrln committed May 19, 2017
commit e5c39bd9079ec7533a1eeaef2bd36b347777588a
32 changes: 22 additions & 10 deletions lib/zlib.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,37 +182,37 @@ class Zlib extends Transform {
this._finishFlushFlag = opts.finishFlush !== undefined ?
opts.finishFlush : constants.Z_FINISH;

if (opts.chunkSize) {
if (opts.chunkSize !== undefined) {
if (opts.chunkSize < constants.Z_MIN_CHUNK) {
throw new RangeError('Invalid chunk size: ' + opts.chunkSize);
}
}

if (opts.windowBits) {
if (opts.windowBits !== undefined) {
if (opts.windowBits < constants.Z_MIN_WINDOWBITS ||
opts.windowBits > constants.Z_MAX_WINDOWBITS) {
throw new RangeError('Invalid windowBits: ' + opts.windowBits);
}
}

if (opts.level) {
if (opts.level !== undefined) {
if (opts.level < constants.Z_MIN_LEVEL ||
opts.level > constants.Z_MAX_LEVEL) {
throw new RangeError('Invalid compression level: ' + opts.level);
}
}

if (opts.memLevel) {
if (opts.memLevel !== undefined) {
if (opts.memLevel < constants.Z_MIN_MEMLEVEL ||
opts.memLevel > constants.Z_MAX_MEMLEVEL) {
throw new RangeError('Invalid memLevel: ' + opts.memLevel);
}
}

if (opts.strategy && isInvalidStrategy(opts.strategy))
if (opts.strategy !== undefined && isInvalidStrategy(opts.strategy))
throw new TypeError('Invalid strategy: ' + opts.strategy);

if (opts.dictionary) {
if (opts.dictionary !== undefined) {
if (!ArrayBuffer.isView(opts.dictionary)) {
throw new TypeError(
'Invalid dictionary: it should be a Buffer, TypedArray, or DataView');
Expand All @@ -224,16 +224,28 @@ class Zlib extends Transform {
this._hadError = false;

var level = constants.Z_DEFAULT_COMPRESSION;
if (typeof opts.level === 'number') level = opts.level;
if (typeof opts.level === 'number' &&
Number.isFinite(opts.level)) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: isn't Number.isFinite() sufficient here? I think it would be easier to read without the typeof check.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, thanks.

level = opts.level;
}

var strategy = constants.Z_DEFAULT_STRATEGY;
if (typeof opts.strategy === 'number') strategy = opts.strategy;
if (typeof opts.strategy === 'number' &&
Number.isFinite(opts.strategy)) {
strategy = opts.strategy;
}

var windowBits = constants.Z_DEFAULT_WINDOWBITS;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't these both just be ternaries?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They could, and I'd like them to be, but I just wrote these in a style consistent with the code above. How about me addressing this comment in a follow-up PR, together with some more refactoring like replacing most vars with lets and consts?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

if (typeof opts.windowBits === 'number') windowBits = opts.windowBits;
if (typeof opts.windowBits === 'number' &&
Number.isFinite(opts.windowBits)) {
windowBits = opts.windowBits;
}

var memLevel = constants.Z_DEFAULT_MEMLEVEL;
if (typeof opts.memLevel === 'number') memLevel = opts.memLevel;
if (typeof opts.memLevel === 'number' &&
Number.isFinite(opts.memLevel)) {
memLevel = opts.memLevel;
}

this._handle.init(windowBits,
level,
Expand Down
24 changes: 24 additions & 0 deletions test/parallel/test-zlib-failed-init.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,27 @@ const zlib = require('zlib');
assert.throws(() => {
zlib.createDeflateRaw({ windowBits: 8 });
}, /^Error: Init error$/);

// Regression tests for bugs in the validation logic.

assert.throws(() => {
zlib.createGzip({ chunkSize: 0 });
}, /^RangeError: Invalid chunk size: 0$/);

assert.throws(() => {
zlib.createGzip({ windowBits: 0 });
}, /^RangeError: Invalid windowBits: 0$/);

assert.throws(() => {
zlib.createGzip({ memLevel: 0 });
}, /^RangeError: Invalid memLevel: 0$/);

{
const stream = zlib.createGzip({ level: NaN });
assert.ok(!Number.isNaN(stream._level));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we check if the values are constants.Z_DEFAULT_COMPRESSION and constants.Z_DEFAULT_STRATEGY respectively?

}

{
const stream = zlib.createGzip({ strategy: NaN });
assert.ok(!Number.isNaN(stream._strategy));
}