Skip to content

Commit 88351a2

Browse files
tniessenaddaleax
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 cecdf7c commit 88351a2

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
@@ -100,7 +100,8 @@ Hash.prototype.update = function update(data, encoding) {
100100

101101
Hash.prototype.digest = function digest(outputEncoding) {
102102
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
103-
return this._handle.digest(outputEncoding);
103+
// Explicit conversion for backward compatibility.
104+
return this._handle.digest(`${outputEncoding}`);
104105
};
105106

106107

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
@@ -3797,9 +3797,8 @@ void Hmac::HmacDigest(const FunctionCallbackInfo<Value>& args) {
37973797

37983798
enum encoding encoding = BUFFER;
37993799
if (args.Length() >= 1) {
3800-
encoding = ParseEncoding(env->isolate(),
3801-
args[0]->ToString(env->isolate()),
3802-
BUFFER);
3800+
CHECK(args[0]->IsString());
3801+
encoding = ParseEncoding(env->isolate(), args[0], BUFFER);
38033802
}
38043803

38053804
unsigned char* md_value = nullptr;
@@ -3921,9 +3920,8 @@ void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
39213920

39223921
enum encoding encoding = BUFFER;
39233922
if (args.Length() >= 1) {
3924-
encoding = ParseEncoding(env->isolate(),
3925-
args[0]->ToString(env->isolate()),
3926-
BUFFER);
3923+
CHECK(args[0]->IsString());
3924+
encoding = ParseEncoding(env->isolate(), args[0], BUFFER);
39273925
}
39283926

39293927
unsigned char md_value[EVP_MAX_MD_SIZE];
@@ -4201,10 +4199,8 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
42014199

42024200
unsigned int len = args.Length();
42034201
enum encoding encoding = BUFFER;
4204-
if (len >= 2 && args[1]->IsString()) {
4205-
encoding = ParseEncoding(env->isolate(),
4206-
args[1]->ToString(env->isolate()),
4207-
BUFFER);
4202+
if (len >= 2) {
4203+
encoding = ParseEncoding(env->isolate(), args[1], BUFFER);
42084204
}
42094205

42104206
node::Utf8Value passphrase(env->isolate(), args[2]);
@@ -4452,9 +4448,7 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
44524448

44534449
enum encoding encoding = UTF8;
44544450
if (args.Length() >= 3) {
4455-
encoding = ParseEncoding(env->isolate(),
4456-
args[2]->ToString(env->isolate()),
4457-
UTF8);
4451+
encoding = ParseEncoding(env->isolate(), args[2], UTF8);
44584452
}
44594453

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