Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zlib: be strict about what strategies are accepted #10934

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
26 changes: 10 additions & 16 deletions lib/zlib.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,12 @@ function isValidFlushFlag(flag) {
flag === constants.Z_BLOCK;
}

const strategies = [constants.Z_FILTERED,
constants.Z_HUFFMAN_ONLY,
constants.Z_RLE,
constants.Z_FIXED,
constants.Z_DEFAULT_STRATEGY];

// the Zlib class they all inherit from
// This thing manages the queue of requests, and returns
// true or false if there is anything in the queue when
Expand Down Expand Up @@ -326,15 +332,8 @@ function Zlib(opts, mode) {
}
}

if (opts.strategy) {
if (opts.strategy != constants.Z_FILTERED &&
opts.strategy != constants.Z_HUFFMAN_ONLY &&
opts.strategy != constants.Z_RLE &&
opts.strategy != constants.Z_FIXED &&
opts.strategy != constants.Z_DEFAULT_STRATEGY) {
throw new Error('Invalid strategy: ' + opts.strategy);
}
}
if (opts.strategy && !(strategies.includes(opts.strategy)))
Copy link
Member

@lpinca lpinca Jan 21, 2017

Choose a reason for hiding this comment

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

Nit: why !(strategies.includes(opts.strategy)) instead of just !strategies.includes(opts.strategy)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Happy to remove it if it's bothersome, but the reason I (sometimes) use the parentheses like that are:

  • clarity of intention
  • helps out people who may not know operator precedence
  • force of habit from !(foo instanceof Buffer) being the correct way to do things because !foo instanceof Buffer means checking that !foo is an instance of Buffer which is not at all the same as foo not an instances of Buffer....

Copy link
Member

Choose a reason for hiding this comment

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

No problem, keep it the way it is.

Copy link
Member

Choose a reason for hiding this comment

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

A range check may be faster than includes ...e.g.

if (opts.strategy >= constants.Z_DEFAULT_STRATEGY &&
   opt.strategy <= constants.Z_FIXED) { ... }

A bit more work to maintain if these values ever change but it avoids the linear scan of the array that includes() requires.

Copy link
Member Author

Choose a reason for hiding this comment

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

Given the overhead of actually compressing and/or decompressing, I suspect such a change for performance purposes in the constructor would be something that would be impossible to measure in any real-world scenario. Counter-examples more than welcome. Barring that, I would prefer the code be clear and not be dependent on unspoken assumptions about constants defined externally.

Copy link
Member

Choose a reason for hiding this comment

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

works for me

throw new Error('Invalid strategy: ' + opts.strategy);

if (opts.dictionary) {
if (!(opts.dictionary instanceof Buffer)) {
Expand Down Expand Up @@ -378,7 +377,7 @@ function Zlib(opts, mode) {
this.once('end', this.close);

Object.defineProperty(this, '_closed', {
get: () => { return !this._handle; },
get: () => !this._handle,
configurable: true,
enumerable: true
});
Expand All @@ -391,13 +390,8 @@ Zlib.prototype.params = function(level, strategy, callback) {
level > constants.Z_MAX_LEVEL) {
throw new RangeError('Invalid compression level: ' + level);
}
if (strategy != constants.Z_FILTERED &&
strategy != constants.Z_HUFFMAN_ONLY &&
strategy != constants.Z_RLE &&
strategy != constants.Z_FIXED &&
strategy != constants.Z_DEFAULT_STRATEGY) {
if (!(strategies.includes(strategy)))
throw new TypeError('Invalid strategy: ' + strategy);
}

if (this._level !== level || this._strategy !== strategy) {
var self = this;
Expand Down
6 changes: 6 additions & 0 deletions test/parallel/test-zlib-deflate-constructors.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ assert.doesNotThrow(
() => { new zlib.Deflate({ strategy: zlib.constants.Z_DEFAULT_STRATEGY}); }
);

// Throws if opt.strategy is the wrong type.
assert.throws(
() => { new zlib.Deflate({strategy: '' + zlib.constants.Z_RLE }); },
/^Error: Invalid strategy: 3$/
);

// Throws if opts.strategy is invalid
assert.throws(
() => { new zlib.Deflate({strategy: 'this is a bogus strategy'}); },
Expand Down