Skip to content

Commit 7678da4

Browse files
tniessenMylesBorins
authored andcommitted
crypto: handle exceptions in hmac/hash.digest
Forced conversion of the encoding parameter to a string within crypto.js, fixing segmentation faults in node_crypto.cc. Fixes: #9819 PR-URL: #12164 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent f1ea367 commit 7678da4

File tree

4 files changed

+35
-14
lines changed

4 files changed

+35
-14
lines changed

lib/crypto.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ Hash.prototype.update = function(data, encoding) {
7878

7979
Hash.prototype.digest = function(outputEncoding) {
8080
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
81-
return this._handle.digest(outputEncoding);
81+
// Explicit conversion for backward compatibility.
82+
return this._handle.digest(`${outputEncoding}`);
8283
};
8384

8485

src/node.cc

+2
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,8 @@ enum encoding ParseEncoding(const char* encoding,
14831483
enum encoding ParseEncoding(Isolate* isolate,
14841484
Local<Value> encoding_v,
14851485
enum encoding default_encoding) {
1486+
CHECK(!encoding_v.IsEmpty());
1487+
14861488
if (!encoding_v->IsString())
14871489
return default_encoding;
14881490

src/node_crypto.cc

+7-13
Original file line numberDiff line numberDiff line change
@@ -3783,9 +3783,8 @@ void Hmac::HmacDigest(const FunctionCallbackInfo<Value>& args) {
37833783

37843784
enum encoding encoding = BUFFER;
37853785
if (args.Length() >= 1) {
3786-
encoding = ParseEncoding(env->isolate(),
3787-
args[0]->ToString(env->isolate()),
3788-
BUFFER);
3786+
CHECK(args[0]->IsString());
3787+
encoding = ParseEncoding(env->isolate(), args[0], BUFFER);
37893788
}
37903789

37913790
unsigned char* md_value = nullptr;
@@ -3907,9 +3906,8 @@ void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
39073906

39083907
enum encoding encoding = BUFFER;
39093908
if (args.Length() >= 1) {
3910-
encoding = ParseEncoding(env->isolate(),
3911-
args[0]->ToString(env->isolate()),
3912-
BUFFER);
3909+
CHECK(args[0]->IsString());
3910+
encoding = ParseEncoding(env->isolate(), args[0], BUFFER);
39133911
}
39143912

39153913
unsigned char md_value[EVP_MAX_MD_SIZE];
@@ -4132,10 +4130,8 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
41324130

41334131
unsigned int len = args.Length();
41344132
enum encoding encoding = BUFFER;
4135-
if (len >= 2 && args[1]->IsString()) {
4136-
encoding = ParseEncoding(env->isolate(),
4137-
args[1]->ToString(env->isolate()),
4138-
BUFFER);
4133+
if (len >= 2) {
4134+
encoding = ParseEncoding(env->isolate(), args[1], BUFFER);
41394135
}
41404136

41414137
node::Utf8Value passphrase(env->isolate(), args[2]);
@@ -4348,9 +4344,7 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
43484344

43494345
enum encoding encoding = UTF8;
43504346
if (args.Length() >= 3) {
4351-
encoding = ParseEncoding(env->isolate(),
4352-
args[2]->ToString(env->isolate()),
4353-
UTF8);
4347+
encoding = ParseEncoding(env->isolate(), args[2], UTF8);
43544348
}
43554349

43564350
ssize_t hlen = StringBytes::Size(env->isolate(), args[1], encoding);

test/parallel/test-regress-GH-9819.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const execFile = require('child_process').execFile;
5+
6+
if (!common.hasCrypto) {
7+
common.skip('missing crypto');
8+
return;
9+
}
10+
11+
const setup = 'const enc = { toString: () => { throw new Error("xyz"); } };';
12+
13+
const scripts = [
14+
'crypto.createHash("sha256").digest(enc)',
15+
'crypto.createHmac("sha256", "msg").digest(enc)'
16+
];
17+
18+
scripts.forEach((script) => {
19+
const node = process.execPath;
20+
const code = setup + ';' + script;
21+
execFile(node, [ '-e', code ], common.mustCall((err, stdout, stderr) => {
22+
assert(stderr.includes('Error: xyz'), 'digest crashes');
23+
}));
24+
});

0 commit comments

Comments
 (0)