diff --git a/doc/api/errors.md b/doc/api/errors.md
index 77da5583719962..82246fff702196 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -1474,6 +1474,11 @@ Used when a given value is out of the accepted range.
Used when an attempt is made to use a `zlib` object after it has already been
closed.
+
+### ERR_ZLIB_INITIALIZATION_FAILED
+
+Used when creation of a [`zlib`][] object fails due to incorrect configuration.
+
[`--force-fips`]: cli.html#cli_force_fips
[`crypto.timingSafeEqual()`]: crypto.html#crypto_crypto_timingsafeequal_a_b
[`dgram.createSocket()`]: dgram.html#dgram_dgram_createsocket_options_callback
@@ -1515,3 +1520,4 @@ closed.
[try-catch]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
[vm]: vm.html
[WHATWG Supported Encodings]: util.html#util_whatwg_supported_encodings
+[`zlib`]: zlib.html
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index 5fe33dafaef894..77cbe33099f92d 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -364,6 +364,7 @@ E('ERR_VALUE_OUT_OF_RANGE', (start, end, value) => {
return `The value of "${start}" must be ${end}. Received "${value}"`;
});
E('ERR_ZLIB_BINDING_CLOSED', 'zlib binding closed');
+E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed');
function invalidArgType(name, expected, actual) {
internalAssert(name, 'name is required');
diff --git a/lib/zlib.js b/lib/zlib.js
index 059b9aac91e76f..751c1765598111 100644
--- a/lib/zlib.js
+++ b/lib/zlib.js
@@ -161,6 +161,12 @@ function Zlib(opts, mode) {
var memLevel = Z_DEFAULT_MEMLEVEL;
var strategy = Z_DEFAULT_STRATEGY;
var dictionary;
+
+ if (typeof mode !== 'number')
+ throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'mode', 'number');
+ if (mode < DEFLATE || mode > UNZIP)
+ throw new errors.RangeError('ERR_OUT_OF_RANGE', 'mode');
+
if (opts) {
chunkSize = opts.chunkSize;
if (chunkSize !== undefined && chunkSize === chunkSize) {
@@ -258,8 +264,15 @@ function Zlib(opts, mode) {
this._hadError = false;
this._writeState = new Uint32Array(2);
- this._handle.init(windowBits, level, memLevel, strategy, this._writeState,
- processCallback, dictionary);
+ if (!this._handle.init(windowBits,
+ level,
+ memLevel,
+ strategy,
+ this._writeState,
+ processCallback,
+ dictionary)) {
+ throw new errors.Error('ERR_ZLIB_INITIALIZATION_FAILED');
+ }
this._outBuffer = Buffer.allocUnsafe(chunkSize);
this._outOffset = 0;
diff --git a/src/node_zlib.cc b/src/node_zlib.cc
index fdfd314222664c..93583181608132 100644
--- a/src/node_zlib.cc
+++ b/src/node_zlib.cc
@@ -418,16 +418,8 @@ class ZCtx : public AsyncWrap {
static void New(const FunctionCallbackInfo& args) {
Environment* env = Environment::GetCurrent(args);
-
- if (args.Length() < 1 || !args[0]->IsInt32()) {
- return env->ThrowTypeError("Bad argument");
- }
+ CHECK(args[0]->IsInt32());
node_zlib_mode mode = static_cast(args[0]->Int32Value());
-
- if (mode < DEFLATE || mode > UNZIP) {
- return env->ThrowTypeError("Bad argument");
- }
-
new ZCtx(env, args.This(), mode);
}
@@ -476,9 +468,14 @@ class ZCtx : public AsyncWrap {
memcpy(dictionary, dictionary_, dictionary_len);
}
- Init(ctx, level, windowBits, memLevel, strategy, write_result,
- write_js_callback, dictionary, dictionary_len);
+ bool ret = Init(ctx, level, windowBits, memLevel, strategy, write_result,
+ write_js_callback, dictionary, dictionary_len);
+ if (!ret) goto end;
+
SetDictionary(ctx);
+
+ end:
+ return args.GetReturnValue().Set(ret);
}
static void Params(const FunctionCallbackInfo& args) {
@@ -495,7 +492,7 @@ class ZCtx : public AsyncWrap {
SetDictionary(ctx);
}
- static void Init(ZCtx *ctx, int level, int windowBits, int memLevel,
+ static bool Init(ZCtx *ctx, int level, int windowBits, int memLevel,
int strategy, uint32_t* write_result,
Local write_js_callback, char* dictionary,
size_t dictionary_len) {
@@ -561,11 +558,12 @@ class ZCtx : public AsyncWrap {
ctx->dictionary_ = nullptr;
}
ctx->mode_ = NONE;
- ctx->env()->ThrowError("Init error");
+ return false;
}
ctx->write_result_ = write_result;
ctx->write_js_callback_.Reset(ctx->env()->isolate(), write_js_callback);
+ return true;
}
static void SetDictionary(ZCtx* ctx) {
diff --git a/test/parallel/test-zlib-failed-init.js b/test/parallel/test-zlib-failed-init.js
index 8597543429e917..7dd53ea3702adf 100644
--- a/test/parallel/test-zlib-failed-init.js
+++ b/test/parallel/test-zlib-failed-init.js
@@ -11,9 +11,13 @@ const zlib = require('zlib');
// no such rejection which is the reason for the version check below
// (http://zlib.net/ChangeLog.txt).
if (!/^1\.2\.[0-8]$/.test(process.versions.zlib)) {
- assert.throws(() => {
- zlib.createDeflateRaw({ windowBits: 8 });
- }, /^Error: Init error$/);
+ common.expectsError(
+ () => zlib.createDeflateRaw({ windowBits: 8 }),
+ {
+ code: 'ERR_ZLIB_INITIALIZATION_FAILED',
+ type: Error,
+ message: 'Initialization failed'
+ });
}
// Regression tests for bugs in the validation logic.