diff --git a/lib/crypto.js b/lib/crypto.js index 72602ff1a43..be3522ba17b 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -78,7 +78,8 @@ Hash.prototype.update = function(data, encoding) { Hash.prototype.digest = function(outputEncoding) { outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; - return this._handle.digest(outputEncoding); + // Explicit conversion for backward compatibility. + return this._handle.digest(`${outputEncoding}`); }; diff --git a/src/node.cc b/src/node.cc index 1db39825e9c..37467490abb 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1483,6 +1483,8 @@ enum encoding ParseEncoding(const char* encoding, enum encoding ParseEncoding(Isolate* isolate, Local encoding_v, enum encoding default_encoding) { + CHECK(!encoding_v.IsEmpty()); + if (!encoding_v->IsString()) return default_encoding; diff --git a/src/node_crypto.cc b/src/node_crypto.cc index f612bf5dc47..ab2fc0cb387 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -3783,9 +3783,8 @@ void Hmac::HmacDigest(const FunctionCallbackInfo& args) { enum encoding encoding = BUFFER; if (args.Length() >= 1) { - encoding = ParseEncoding(env->isolate(), - args[0]->ToString(env->isolate()), - BUFFER); + CHECK(args[0]->IsString()); + encoding = ParseEncoding(env->isolate(), args[0], BUFFER); } unsigned char* md_value = nullptr; @@ -3907,9 +3906,8 @@ void Hash::HashDigest(const FunctionCallbackInfo& args) { enum encoding encoding = BUFFER; if (args.Length() >= 1) { - encoding = ParseEncoding(env->isolate(), - args[0]->ToString(env->isolate()), - BUFFER); + CHECK(args[0]->IsString()); + encoding = ParseEncoding(env->isolate(), args[0], BUFFER); } unsigned char md_value[EVP_MAX_MD_SIZE]; @@ -4132,10 +4130,8 @@ void Sign::SignFinal(const FunctionCallbackInfo& args) { unsigned int len = args.Length(); enum encoding encoding = BUFFER; - if (len >= 2 && args[1]->IsString()) { - encoding = ParseEncoding(env->isolate(), - args[1]->ToString(env->isolate()), - BUFFER); + if (len >= 2) { + encoding = ParseEncoding(env->isolate(), args[1], BUFFER); } node::Utf8Value passphrase(env->isolate(), args[2]); @@ -4348,9 +4344,7 @@ void Verify::VerifyFinal(const FunctionCallbackInfo& args) { enum encoding encoding = UTF8; if (args.Length() >= 3) { - encoding = ParseEncoding(env->isolate(), - args[2]->ToString(env->isolate()), - UTF8); + encoding = ParseEncoding(env->isolate(), args[2], UTF8); } ssize_t hlen = StringBytes::Size(env->isolate(), args[1], encoding); diff --git a/test/parallel/test-regress-GH-9819.js b/test/parallel/test-regress-GH-9819.js new file mode 100644 index 00000000000..f043bc3b284 --- /dev/null +++ b/test/parallel/test-regress-GH-9819.js @@ -0,0 +1,24 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const execFile = require('child_process').execFile; + +if (!common.hasCrypto) { + common.skip('missing crypto'); + return; +} + +const setup = 'const enc = { toString: () => { throw new Error("xyz"); } };'; + +const scripts = [ + 'crypto.createHash("sha256").digest(enc)', + 'crypto.createHmac("sha256", "msg").digest(enc)' +]; + +scripts.forEach((script) => { + const node = process.execPath; + const code = setup + ';' + script; + execFile(node, [ '-e', code ], common.mustCall((err, stdout, stderr) => { + assert(stderr.includes('Error: xyz'), 'digest crashes'); + })); +});