-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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: fix node crashing on invalid options #13098
Conversation
The main reason behind this commit is fixing the Node process crashing when zlib rejects the given options. Besides that issue, which got reported and which is linked to this commit, it turned out that Node also used to crash when a non-numeric value was passed as the `windowBits` or the `memLevel` option. This was fixed somewhat inadvertently; initially it was just a stylistic change to avoid lines spanning longer than 80 characters that was written in a manner consistent with surrounding code. Fixes: nodejs#13082
@aqrln did something change with zlib 1.2.11? zlib.createDeflateRaw({ windowBits: 8 }) worked fine with Node.js 6.10.1. |
I wonder if it makes sense to use this remedy
in order to avoid the breaking change. |
src/node_zlib.cc
Outdated
SetDictionary(ctx); | ||
|
||
args.GetReturnValue().Set(Boolean::New(args.GetIsolate(), result)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m pretty sure you don’t need Boolean::New
here :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, didn't know that :)
lib/zlib.js
Outdated
process.nextTick(() => { | ||
this.emit('error', error); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this error should still be thrown synchronously, if there is one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That'll make it impossible to catch this error since there's on object returned to userland code yet to listen to the error
event on. That's basically the reason for all this machinery, otherwise @cjihrig's one-line fix would be just fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could change the ZCtx::Error(ctx, "Init error");
line to throw an error instead … that should work, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... yes, it should. And there would be no need for all those changes in zlib.js
then.
src/node_zlib.cc
Outdated
@@ -553,6 +556,9 @@ class ZCtx : public AsyncWrap { | |||
|
|||
if (ctx->err_ != Z_OK) { | |||
ZCtx::Error(ctx, "Init error"); | |||
if (dictionary != nullptr) | |||
delete[] dictionary; | |||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’d have to admit I prefer the solution suggested by @cjihrig in #13082 (comment) (or just move this error-checking block to the end of the Init()
function, after ctx->init_done_ = true
)
@lpinca do you suggest making |
@aqrln yes use 15 (default value) when 8 is passed, not sure if it is a good idea though. Maybe it is better to do this in userland code. |
Throw an Error synchronously instead of fiddling with 'error' events.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a couple comments.
doc/api/zlib.md
Outdated
@@ -437,6 +437,10 @@ added: v0.5.8 | |||
|
|||
Returns a new [DeflateRaw][] object with an [options][]. | |||
|
|||
**Note:** zlib library rejects requests for 256-byte windows (i.e., |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe start the note with "The"
lib/zlib.js
Outdated
@@ -229,9 +229,15 @@ class Zlib extends Transform { | |||
var strategy = constants.Z_DEFAULT_STRATEGY; | |||
if (typeof opts.strategy === 'number') strategy = opts.strategy; | |||
|
|||
this._handle.init(opts.windowBits || constants.Z_DEFAULT_WINDOWBITS, | |||
var windowBits = constants.Z_DEFAULT_WINDOWBITS; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 var
s with let
s and const
s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure
// (http://zlib.net/manual.html#Advanced) | ||
assert.throws(() => { | ||
zlib.createDeflateRaw({ windowBits: 8 }); | ||
}, /Init error/); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you match the full error here using ^
and $
.
Does is makes sense to throw early if |
@lpinca I think it would. Are you thinking of doing that instead of this PR, or in addition to? I think the changes here are still good independently |
@lpinca idk ¯\_(ツ)_/¯ Theoretically, it may change in the future:
|
I would make it in addition of these changes to make the error message consistent, but then the "Init error" would not be easy to test. |
Yeah, we might do that just for the sake of making the error message more sensible. Seems like all the other ways to break |
Yes and this explains why it didn't crash before zlib 1.2.11. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with or without the additional check for opts.windowBits === 8
.
That's quite easy to do (aqrln@bf63a37), but I am not really sure about it. I actually see the point in doing so, but being able to test that any sort of failure can be caught seems to be more important, so I'm inclined to leave this PR as it is now unless others would prefer to pull either that commit or something similar to it here. |
CI for the latest changes: https://ci.nodejs.org/job/node-test-pull-request/8159/ |
lib/zlib.js
Outdated
if (typeof opts.windowBits === 'number') windowBits = opts.windowBits; | ||
|
||
var memLevel = constants.Z_DEFAULT_MEMLEVEL; | ||
if (typeof opts.memLevel === 'number') memLevel = opts.memLevel; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change alters the existing behaviour a little. If we pass NaN
or Zero, they used to pick the default value earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great catch, thanks. It uncovers a whole bunch of bugs in the validation logic above, i.e., I wanted to say that zero would be caught before this line, but after trying it out it appeared to be not. And it was also possible to pass NaN
as the value of some of the other options, like level
.
I agree. As you said this may change again and 8 could be restored as valid value so it's probably better to keep this as is. |
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: #13098 Fixes: #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]>
This is a partial backport of semver-patch bits of 9e4660b. 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. PR-URL: nodejs#13098 Backport-PR-URL: nodejs#13201 Fixes: nodejs#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]>
This is a partial backport of semver-patch bits of 9e4660b. 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. PR-URL: #13098 Backport-PR-URL: #13201 Fixes: #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]>
This is a partial backport of semver-patch bits of 9e4660b. 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. PR-URL: #13098 Backport-PR-URL: #13201 Fixes: #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]>
This LTS release comes with 221 commits. This includes 80 which are test related, 52 which are doc related, 32 which are build / tool related and 10 commits which are updates to dependencies. Notable Changes: * configure: - add mips64el to valid_arch (Aditya Anand) - #13620 * crypto: - Updated root certificates based on [NSS 3.30] (Ben Noordhuis) - #13279 - #12402 - https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/NSS_3.30_release_notes * deps: - upgrade OpenSSL to version 1.0.2.l (Shigeki Ohtsu) - #12913 * http: - parse errors are now reported when NODE_DEBUG=http (Sam Roberts) - #13206 - Agent construction can now be envoked without `new` (cjihrig) - #12927 * zlib: - node will now throw an Error when zlib rejects the value of windowBits, instead of crashing (Alexey Orlenko) - #13098 PR-URL: #14356
This LTS release comes with 221 commits. This includes 80 which are test related, 52 which are doc related, 32 which are build / tool related and 10 commits which are updates to dependencies. Notable Changes: * configure: - add mips64el to valid_arch (Aditya Anand) - #13620 * crypto: - Updated root certificates based on [NSS 3.30] (Ben Noordhuis) - #13279 - #12402 - https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/NSS_3.30_release_notes * deps: - upgrade OpenSSL to version 1.0.2.l (Shigeki Ohtsu) - #12913 * http: - parse errors are now reported when NODE_DEBUG=http (Sam Roberts) - #13206 - Agent construction can now be envoked without `new` (cjihrig) - #12927 * zlib: - node will now throw an Error when zlib rejects the value of windowBits, instead of crashing (Alexey Orlenko) - #13098 PR-URL: #14356
Unset `mode_` when initializing the zlib stream failed, so that we don’t try to call the zlib end functions (`deflateEnd()` etc.) when cleaning up in `ZCtx::Close()`. Fixes: nodejs#14178 Ref: nodejs#13098
Unset `mode_` when initializing the zlib stream failed, so that we don’t try to call the zlib end functions (`deflateEnd()` etc.) when cleaning up in `ZCtx::Close()`. Fixes: #14178 Ref: #13098 PR-URL: #14666 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Alexey Orlenko <[email protected]>
Unset `mode_` when initializing the zlib stream failed, so that we don’t try to call the zlib end functions (`deflateEnd()` etc.) when cleaning up in `ZCtx::Close()`. Fixes: #14178 Ref: #13098 PR-URL: #14666 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Alexey Orlenko <[email protected]>
Unset `mode_` when initializing the zlib stream failed, so that we don’t try to call the zlib end functions (`deflateEnd()` etc.) when cleaning up in `ZCtx::Close()`. Fixes: #14178 Ref: #13098 PR-URL: #14666 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Alexey Orlenko <[email protected]>
This is a partial backport of semver-patch bits of 9e4660b. 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. PR-URL: nodejs#13098 Fixes: nodejs#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]>
Unset `mode_` when initializing the zlib stream failed, so that we don’t try to call the zlib end functions (`deflateEnd()` etc.) when cleaning up in `ZCtx::Close()`. Fixes: nodejs#14178 Ref: nodejs#13098 PR-URL: nodejs#14666 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Alexey Orlenko <[email protected]>
This is a partial backport of semver-patch bits of 9e4660b. 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. Backport-PR-URL: #14860 PR-URL: #13098 Fixes: #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]>
Unset `mode_` when initializing the zlib stream failed, so that we don’t try to call the zlib end functions (`deflateEnd()` etc.) when cleaning up in `ZCtx::Close()`. Fixes: #14178 Ref: #13098 Backport-PR-URL: #14860 PR-URL: #14666 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Alexey Orlenko <[email protected]>
This is a partial backport of semver-patch bits of 9e4660b. 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. Backport-PR-URL: #14860 PR-URL: #13098 Fixes: #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]>
Unset `mode_` when initializing the zlib stream failed, so that we don’t try to call the zlib end functions (`deflateEnd()` etc.) when cleaning up in `ZCtx::Close()`. Fixes: #14178 Ref: #13098 Backport-PR-URL: #14860 PR-URL: #14666 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Alexey Orlenko <[email protected]>
This PR fixes the Node process crashing when constructors of classes of the
zlib
module are given invalid options.windowBits
, instead of crashing with an assertion.windowBits
andmemLevel
options consistently with other ones and don't crash when non-numeric values are given.Fixes: #13082
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
zlib