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: https://github.com/nodejs/node/issues/9819 PR-URL: https://github.com/nodejs/node/pull/12164 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
cecdf7c118
commit
88351a22ed
@ -100,7 +100,8 @@ Hash.prototype.update = function update(data, encoding) {
|
|||||||
|
|
||||||
Hash.prototype.digest = function digest(outputEncoding) {
|
Hash.prototype.digest = function digest(outputEncoding) {
|
||||||
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
|
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
|
||||||
return this._handle.digest(outputEncoding);
|
// Explicit conversion for backward compatibility.
|
||||||
|
return this._handle.digest(`${outputEncoding}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1483,6 +1483,8 @@ enum encoding ParseEncoding(const char* encoding,
|
|||||||
enum encoding ParseEncoding(Isolate* isolate,
|
enum encoding ParseEncoding(Isolate* isolate,
|
||||||
Local<Value> encoding_v,
|
Local<Value> encoding_v,
|
||||||
enum encoding default_encoding) {
|
enum encoding default_encoding) {
|
||||||
|
CHECK(!encoding_v.IsEmpty());
|
||||||
|
|
||||||
if (!encoding_v->IsString())
|
if (!encoding_v->IsString())
|
||||||
return default_encoding;
|
return default_encoding;
|
||||||
|
|
||||||
|
@ -3797,9 +3797,8 @@ void Hmac::HmacDigest(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
enum encoding encoding = BUFFER;
|
enum encoding encoding = BUFFER;
|
||||||
if (args.Length() >= 1) {
|
if (args.Length() >= 1) {
|
||||||
encoding = ParseEncoding(env->isolate(),
|
CHECK(args[0]->IsString());
|
||||||
args[0]->ToString(env->isolate()),
|
encoding = ParseEncoding(env->isolate(), args[0], BUFFER);
|
||||||
BUFFER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* md_value = nullptr;
|
unsigned char* md_value = nullptr;
|
||||||
@ -3921,9 +3920,8 @@ void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
enum encoding encoding = BUFFER;
|
enum encoding encoding = BUFFER;
|
||||||
if (args.Length() >= 1) {
|
if (args.Length() >= 1) {
|
||||||
encoding = ParseEncoding(env->isolate(),
|
CHECK(args[0]->IsString());
|
||||||
args[0]->ToString(env->isolate()),
|
encoding = ParseEncoding(env->isolate(), args[0], BUFFER);
|
||||||
BUFFER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char md_value[EVP_MAX_MD_SIZE];
|
unsigned char md_value[EVP_MAX_MD_SIZE];
|
||||||
@ -4201,10 +4199,8 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
unsigned int len = args.Length();
|
unsigned int len = args.Length();
|
||||||
enum encoding encoding = BUFFER;
|
enum encoding encoding = BUFFER;
|
||||||
if (len >= 2 && args[1]->IsString()) {
|
if (len >= 2) {
|
||||||
encoding = ParseEncoding(env->isolate(),
|
encoding = ParseEncoding(env->isolate(), args[1], BUFFER);
|
||||||
args[1]->ToString(env->isolate()),
|
|
||||||
BUFFER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node::Utf8Value passphrase(env->isolate(), args[2]);
|
node::Utf8Value passphrase(env->isolate(), args[2]);
|
||||||
@ -4452,9 +4448,7 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
enum encoding encoding = UTF8;
|
enum encoding encoding = UTF8;
|
||||||
if (args.Length() >= 3) {
|
if (args.Length() >= 3) {
|
||||||
encoding = ParseEncoding(env->isolate(),
|
encoding = ParseEncoding(env->isolate(), args[2], UTF8);
|
||||||
args[2]->ToString(env->isolate()),
|
|
||||||
UTF8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t hlen = StringBytes::Size(env->isolate(), args[1], encoding);
|
ssize_t hlen = StringBytes::Size(env->isolate(), args[1], encoding);
|
||||||
|
24
test/parallel/test-regress-GH-9819.js
Normal file
24
test/parallel/test-regress-GH-9819.js
Normal file
@ -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');
|
||||||
|
}));
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user