Skip to content

Commit 67d2114

Browse files
tniessenitaloacasas
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 <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 3b765f5 commit 67d2114

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 update(data, encoding) {
7878

7979
Hash.prototype.digest = function digest(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
@@ -1443,6 +1443,8 @@ enum encoding ParseEncoding(const char* encoding,
14431443
enum encoding ParseEncoding(Isolate* isolate,
14441444
Local<Value> encoding_v,
14451445
enum encoding default_encoding) {
1446+
CHECK(!encoding_v.IsEmpty());
1447+
14461448
if (!encoding_v->IsString())
14471449
return default_encoding;
14481450

src/node_crypto.cc

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

37703770
enum encoding encoding = BUFFER;
37713771
if (args.Length() >= 1) {
3772-
encoding = ParseEncoding(env->isolate(),
3773-
args[0]->ToString(env->isolate()),
3774-
BUFFER);
3772+
CHECK(args[0]->IsString());
3773+
encoding = ParseEncoding(env->isolate(), args[0], BUFFER);
37753774
}
37763775

37773776
unsigned char* md_value = nullptr;
@@ -3893,9 +3892,8 @@ void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
38933892

38943893
enum encoding encoding = BUFFER;
38953894
if (args.Length() >= 1) {
3896-
encoding = ParseEncoding(env->isolate(),
3897-
args[0]->ToString(env->isolate()),
3898-
BUFFER);
3895+
CHECK(args[0]->IsString());
3896+
encoding = ParseEncoding(env->isolate(), args[0], BUFFER);
38993897
}
39003898

39013899
unsigned char md_value[EVP_MAX_MD_SIZE];
@@ -4118,10 +4116,8 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
41184116

41194117
unsigned int len = args.Length();
41204118
enum encoding encoding = BUFFER;
4121-
if (len >= 2 && args[1]->IsString()) {
4122-
encoding = ParseEncoding(env->isolate(),
4123-
args[1]->ToString(env->isolate()),
4124-
BUFFER);
4119+
if (len >= 2) {
4120+
encoding = ParseEncoding(env->isolate(), args[1], BUFFER);
41254121
}
41264122

41274123
node::Utf8Value passphrase(env->isolate(), args[2]);
@@ -4334,9 +4330,7 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
43344330

43354331
enum encoding encoding = UTF8;
43364332
if (args.Length() >= 3) {
4337-
encoding = ParseEncoding(env->isolate(),
4338-
args[2]->ToString(env->isolate()),
4339-
UTF8);
4333+
encoding = ParseEncoding(env->isolate(), args[2], UTF8);
43404334
}
43414335

43424336
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)