Skip to content

Commit

Permalink
src: avoid heap allocation in sign.final()
Browse files Browse the repository at this point in the history
Put the 8 kB initial buffer on the stack first and don't copy it to the
heap until its exact size is known (which is normally much smaller.)

PR-URL: #14122
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
bnoordhuis authored and addaleax committed Jul 18, 2017
1 parent efb7aef commit 174f8c8
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 19 deletions.
27 changes: 9 additions & 18 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4147,7 +4147,7 @@ static int Node_SignFinal(EVP_MD_CTX* mdctx, unsigned char* md,
SignBase::Error Sign::SignFinal(const char* key_pem,
int key_pem_len,
const char* passphrase,
unsigned char** sig,
unsigned char* sig,
unsigned int* sig_len,
int padding,
int salt_len) {
Expand Down Expand Up @@ -4196,7 +4196,7 @@ SignBase::Error Sign::SignFinal(const char* key_pem,
}
#endif // NODE_FIPS_MODE

if (Node_SignFinal(&mdctx_, *sig, sig_len, pkey, padding, salt_len))
if (Node_SignFinal(&mdctx_, sig, sig_len, pkey, padding, salt_len))
fatal = false;

initialised_ = false;
Expand All @@ -4222,9 +4222,6 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
Sign* sign;
ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder());

unsigned char* md_value;
unsigned int md_len;

unsigned int len = args.Length();

node::Utf8Value passphrase(env->isolate(), args[1]);
Expand All @@ -4243,30 +4240,24 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
CHECK(maybe_salt_len.IsJust());
int salt_len = maybe_salt_len.ToChecked();

md_len = 8192; // Maximum key size is 8192 bits
md_value = new unsigned char[md_len];

ClearErrorOnReturn clear_error_on_return;
unsigned char md_value[8192];
unsigned int md_len = sizeof(md_value);

Error err = sign->SignFinal(
buf,
buf_len,
len >= 2 && !args[1]->IsNull() ? *passphrase : nullptr,
&md_value,
md_value,
&md_len,
padding,
salt_len);
if (err != kSignOk) {
delete[] md_value;
md_value = nullptr;
md_len = 0;
if (err != kSignOk)
return sign->CheckThrow(err);
}

Local<Object> rc = Buffer::Copy(env->isolate(),
reinterpret_cast<const char*>(md_value),
md_len).ToLocalChecked();
delete[] md_value;
Local<Object> rc =
Buffer::Copy(env, reinterpret_cast<char*>(md_value), md_len)
.ToLocalChecked();
args.GetReturnValue().Set(rc);
}

Expand Down
2 changes: 1 addition & 1 deletion src/node_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ class Sign : public SignBase {
Error SignFinal(const char* key_pem,
int key_pem_len,
const char* passphrase,
unsigned char** sig,
unsigned char* sig,
unsigned int *sig_len,
int padding,
int saltlen);
Expand Down

0 comments on commit 174f8c8

Please sign in to comment.