Browse Source

src: remove extra heap allocations in CipherBase

Don't allocate + copy + free; allocate and fill in place, then hand off
the pointer to Buffer::New().

Avoids unnecessary heap allocations in the following methods:

- crypto.Cipher#final()
- crypto.Cipher#update()
- crypto.Cipheriv#final()
- crypto.Cipheriv#update()
- crypto.Decipher#final()
- crypto.Decipher#update()
- crypto.Decipheriv#final()
- crypto.Decipheriv#update()
- crypto.privateDecrypt()
- crypto.privateEncrypt()
- crypto.publicDecrypt()
- crypto.publicEncrypt()

PR-URL: https://github.com/nodejs/node/pull/14122
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
v6
Ben Noordhuis 7 years ago
parent
commit
6ac092848a
  1. 28
      src/node_crypto.cc

28
src/node_crypto.cc

@ -3561,7 +3561,7 @@ bool CipherBase::Update(const char* data,
} }
*out_len = len + EVP_CIPHER_CTX_block_size(&ctx_); *out_len = len + EVP_CIPHER_CTX_block_size(&ctx_);
*out = new unsigned char[*out_len]; *out = Malloc<unsigned char>(static_cast<size_t>(*out_len));
return EVP_CipherUpdate(&ctx_, return EVP_CipherUpdate(&ctx_,
*out, *out,
out_len, out_len,
@ -3595,7 +3595,7 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
} }
if (!r) { if (!r) {
delete[] out; free(out);
return ThrowCryptoError(env, return ThrowCryptoError(env,
ERR_get_error(), ERR_get_error(),
"Trying to add data in unsupported state"); "Trying to add data in unsupported state");
@ -3603,9 +3603,7 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
CHECK(out != nullptr || out_len == 0); CHECK(out != nullptr || out_len == 0);
Local<Object> buf = Local<Object> buf =
Buffer::Copy(env, reinterpret_cast<char*>(out), out_len).ToLocalChecked(); Buffer::New(env, reinterpret_cast<char*>(out), out_len).ToLocalChecked();
if (out)
delete[] out;
args.GetReturnValue().Set(buf); args.GetReturnValue().Set(buf);
} }
@ -3633,7 +3631,8 @@ bool CipherBase::Final(unsigned char** out, int *out_len) {
if (!initialised_) if (!initialised_)
return false; return false;
*out = new unsigned char[EVP_CIPHER_CTX_block_size(&ctx_)]; *out = Malloc<unsigned char>(
static_cast<size_t>(EVP_CIPHER_CTX_block_size(&ctx_)));
int r = EVP_CipherFinal_ex(&ctx_, *out, out_len); int r = EVP_CipherFinal_ex(&ctx_, *out, out_len);
if (r && kind_ == kCipher) { if (r && kind_ == kCipher) {
@ -3670,7 +3669,7 @@ void CipherBase::Final(const FunctionCallbackInfo<Value>& args) {
bool r = cipher->Final(&out_value, &out_len); bool r = cipher->Final(&out_value, &out_len);
if (out_len <= 0 || !r) { if (out_len <= 0 || !r) {
delete[] out_value; free(out_value);
out_value = nullptr; out_value = nullptr;
out_len = 0; out_len = 0;
if (!r) { if (!r) {
@ -3684,12 +3683,11 @@ void CipherBase::Final(const FunctionCallbackInfo<Value>& args) {
} }
} }
Local<Object> buf = Buffer::Copy( Local<Object> buf = Buffer::New(
env, env,
reinterpret_cast<char*>(out_value), reinterpret_cast<char*>(out_value),
out_len).ToLocalChecked(); out_len).ToLocalChecked();
args.GetReturnValue().Set(buf); args.GetReturnValue().Set(buf);
delete[] out_value;
} }
@ -4560,7 +4558,7 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
if (EVP_PKEY_cipher(ctx, nullptr, out_len, data, len) <= 0) if (EVP_PKEY_cipher(ctx, nullptr, out_len, data, len) <= 0)
goto exit; goto exit;
*out = new unsigned char[*out_len]; *out = Malloc<unsigned char>(*out_len);
if (EVP_PKEY_cipher(ctx, *out, out_len, data, len) <= 0) if (EVP_PKEY_cipher(ctx, *out, out_len, data, len) <= 0)
goto exit; goto exit;
@ -4615,7 +4613,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
&out_len); &out_len);
if (out_len == 0 || !r) { if (out_len == 0 || !r) {
delete[] out_value; free(out_value);
out_value = nullptr; out_value = nullptr;
out_len = 0; out_len = 0;
if (!r) { if (!r) {
@ -4624,12 +4622,10 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
} }
} }
Local<Object> vbuf = Buffer::Copy( Local<Object> vbuf =
env, Buffer::New(env, reinterpret_cast<char*>(out_value), out_len)
reinterpret_cast<char*>(out_value), .ToLocalChecked();
out_len).ToLocalChecked();
args.GetReturnValue().Set(vbuf); args.GetReturnValue().Set(vbuf);
delete[] out_value;
} }

Loading…
Cancel
Save