Skip to content
This repository has been archived by the owner on Mar 4, 2020. It is now read-only.

Commit

Permalink
Allocate memory of Buffer with V8's allocator
Browse files Browse the repository at this point in the history
  • Loading branch information
zcbenz authored and deepak1556 committed Mar 8, 2018
1 parent a038b70 commit 813a45f
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 48 deletions.
25 changes: 14 additions & 11 deletions src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ bool zero_fill_all_buffers = false;

namespace {

inline void* BufferMalloc(size_t length) {
return zero_fill_all_buffers ? node::UncheckedCalloc(length) :
node::UncheckedMalloc(length);
inline void* BufferMalloc(v8::Isolate* isolate, size_t length) {
auto* allocator = isolate->GetArrayBufferAllocator();
return zero_fill_all_buffers ? allocator->Allocate(length) :
allocator->AllocateUninitialized(length);
}

} // namespace
Expand Down Expand Up @@ -246,7 +247,7 @@ MaybeLocal<Object> New(Isolate* isolate,
char* data = nullptr;

if (length > 0) {
data = static_cast<char*>(BufferMalloc(length));
data = static_cast<char*>(BufferMalloc(isolate, length));

if (data == nullptr)
return Local<Object>();
Expand All @@ -255,10 +256,11 @@ MaybeLocal<Object> New(Isolate* isolate,
CHECK(actual <= length);

if (actual == 0) {
free(data);
isolate->GetArrayBufferAllocator()->Free(data, length);
data = nullptr;
} else if (actual < length) {
data = node::Realloc(data, actual);
// We should call realloc here, but v8::ArrayBufferAllocator does not
// provide such ability.
}
}

Expand All @@ -267,7 +269,7 @@ MaybeLocal<Object> New(Isolate* isolate,
return scope.Escape(buf);

// Object failed to be created. Clean up resources.
free(data);
isolate->GetArrayBufferAllocator()->Free(data, length);
return Local<Object>();
}

Expand All @@ -291,7 +293,7 @@ MaybeLocal<Object> New(Environment* env, size_t length) {

void* data;
if (length > 0) {
data = BufferMalloc(length);
data = BufferMalloc(env->isolate(), length);
if (data == nullptr)
return Local<Object>();
} else {
Expand All @@ -307,7 +309,7 @@ MaybeLocal<Object> New(Environment* env, size_t length) {

if (ui.IsEmpty()) {
// Object failed to be created. Clean up resources.
free(data);
env->isolate()->GetArrayBufferAllocator()->Free(data, length);
}

return scope.Escape(ui.FromMaybe(Local<Uint8Array>()));
Expand All @@ -332,10 +334,11 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
return Local<Object>();
}

auto* allocator = env->isolate()->GetArrayBufferAllocator();
void* new_data;
if (length > 0) {
CHECK_NE(data, nullptr);
new_data = node::UncheckedMalloc(length);
new_data = allocator->AllocateUninitialized(length);
if (new_data == nullptr)
return Local<Object>();
memcpy(new_data, data, length);
Expand All @@ -352,7 +355,7 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {

if (ui.IsEmpty()) {
// Object failed to be created. Clean up resources.
free(new_data);
allocator->Free(new_data, length);
}

return scope.Escape(ui.FromMaybe(Local<Uint8Array>()));
Expand Down
73 changes: 47 additions & 26 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2114,7 +2114,8 @@ void SSLWrap<Base>::GetSession(const FunctionCallbackInfo<Value>& args) {
int slen = i2d_SSL_SESSION(sess, nullptr);
CHECK_GT(slen, 0);

char* sbuf = Malloc(slen);
auto* allocator = env->isolate()->GetArrayBufferAllocator();
char* sbuf = static_cast<char*>(allocator->AllocateUninitialized(slen));
unsigned char* p = reinterpret_cast<unsigned char*>(sbuf);
i2d_SSL_SESSION(sess, &p);
args.GetReturnValue().Set(Buffer::New(env, sbuf, slen).ToLocalChecked());
Expand Down Expand Up @@ -3894,8 +3895,9 @@ bool CipherBase::Update(const char* data,
auth_tag_len_ = 0;
}

auto* allocator = env()->isolate()->GetArrayBufferAllocator();
*out_len = len + EVP_CIPHER_CTX_block_size(ctx_);
*out = Malloc<unsigned char>(static_cast<size_t>(*out_len));
*out = static_cast<unsigned char*>(allocator->AllocateUninitialized(*out_len));
return EVP_CipherUpdate(ctx_,
*out,
out_len,
Expand Down Expand Up @@ -3929,7 +3931,8 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
}

if (!r) {
free(out);
auto* allocator = env->isolate()->GetArrayBufferAllocator();
allocator->Free(out, out_len);
return ThrowCryptoError(env,
ERR_get_error(),
"Trying to add data in unsupported state");
Expand Down Expand Up @@ -3965,8 +3968,9 @@ bool CipherBase::Final(unsigned char** out, int *out_len) {
if (ctx_ == nullptr)
return false;

*out = Malloc<unsigned char>(
static_cast<size_t>(EVP_CIPHER_CTX_block_size(ctx_)));
auto* allocator = env()->isolate()->GetArrayBufferAllocator();
*out = static_cast<unsigned char*>(allocator->AllocateUninitialized(
EVP_CIPHER_CTX_block_size(ctx_)));
int r = EVP_CipherFinal_ex(ctx_, *out, out_len);

if (r == 1 && kind_ == kCipher && IsAuthenticatedMode()) {
Expand Down Expand Up @@ -3998,7 +4002,8 @@ void CipherBase::Final(const FunctionCallbackInfo<Value>& args) {
bool r = cipher->Final(&out_value, &out_len);

if (out_len <= 0 || !r) {
free(out_value);
auto* allocator = env->isolate()->GetArrayBufferAllocator();
allocator->Free(out_value, out_len);
out_value = nullptr;
out_len = 0;
if (!r) {
Expand Down Expand Up @@ -4712,7 +4717,8 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
template <PublicKeyCipher::Operation operation,
PublicKeyCipher::EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
PublicKeyCipher::EVP_PKEY_cipher_t EVP_PKEY_cipher>
bool PublicKeyCipher::Cipher(const char* key_pem,
bool PublicKeyCipher::Cipher(Environment* env,
const char* key_pem,
int key_pem_len,
const char* passphrase,
int padding,
Expand All @@ -4725,6 +4731,7 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
BIO* bp = nullptr;
X509* x509 = nullptr;
bool fatal = true;
auto* allocator = env->isolate()->GetArrayBufferAllocator();

bp = BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len);
if (bp == nullptr)
Expand Down Expand Up @@ -4777,7 +4784,7 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
if (EVP_PKEY_cipher(ctx, nullptr, out_len, data, len) <= 0)
goto exit;

*out = Malloc<unsigned char>(*out_len);
*out = static_cast<unsigned char*>(allocator->AllocateUninitialized(*out_len));

if (EVP_PKEY_cipher(ctx, *out, out_len, data, len) <= 0)
goto exit;
Expand Down Expand Up @@ -4822,6 +4829,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
ClearErrorOnReturn clear_error_on_return;

bool r = Cipher<operation, EVP_PKEY_cipher_init, EVP_PKEY_cipher>(
env,
kbuf,
klen,
args.Length() >= 3 && !args[2]->IsNull() ? *passphrase : nullptr,
Expand All @@ -4832,7 +4840,8 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
&out_len);

if (out_len == 0 || !r) {
free(out_value);
auto* allocator = env->isolate()->GetArrayBufferAllocator();
allocator->Free(out_value, out_len);
out_value = nullptr;
out_len = 0;
if (!r) {
Expand Down Expand Up @@ -5037,7 +5046,8 @@ void DiffieHellman::GenerateKeys(const FunctionCallbackInfo<Value>& args) {
const BIGNUM* pub_key;
DH_get0_key(diffieHellman->dh, &pub_key, nullptr);
size_t size = BN_num_bytes(pub_key);
char* data = Malloc(size);
auto* allocator = env->isolate()->GetArrayBufferAllocator();
char* data = static_cast<char*>(allocator->AllocateUninitialized(size));
BN_bn2bin(pub_key, reinterpret_cast<unsigned char*>(data));
args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked());
}
Expand All @@ -5056,7 +5066,8 @@ void DiffieHellman::GetField(const FunctionCallbackInfo<Value>& args,
if (num == nullptr) return env->ThrowError(err_if_null);

size_t size = BN_num_bytes(num);
char* data = Malloc(size);
auto* allocator = env->isolate()->GetArrayBufferAllocator();
char* data = static_cast<char*>(allocator->AllocateUninitialized(size));
BN_bn2bin(num, reinterpret_cast<unsigned char*>(data));
args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked());
}
Expand Down Expand Up @@ -5121,7 +5132,8 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
}

int dataSize = DH_size(diffieHellman->dh);
char* data = Malloc(dataSize);
auto* allocator = env->isolate()->GetArrayBufferAllocator();
char* data = static_cast<char*>(allocator->AllocateUninitialized(dataSize));

int size = DH_compute_key(reinterpret_cast<unsigned char*>(data),
key,
Expand All @@ -5133,7 +5145,7 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {

checked = DH_check_pub_key(diffieHellman->dh, key, &checkResult);
BN_free(key);
free(data);
allocator->Free(data, dataSize);

if (!checked) {
return ThrowCryptoError(env, ERR_get_error(), "Invalid Key");
Expand Down Expand Up @@ -5338,14 +5350,15 @@ void ECDH::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
return;

// NOTE: field_size is in bits
auto* allocator = env->isolate()->GetArrayBufferAllocator();
int field_size = EC_GROUP_get_degree(ecdh->group_);
size_t out_len = (field_size + 7) / 8;
char* out = node::Malloc(out_len);
char* out = static_cast<char*>(allocator->AllocateUninitialized(out_len));

int r = ECDH_compute_key(out, out_len, pub, ecdh->key_, nullptr);
EC_POINT_free(pub);
if (!r) {
free(out);
allocator->Free(out, out_len);
return env->ThrowError("Failed to compute ECDH key");
}

Expand Down Expand Up @@ -5375,11 +5388,13 @@ void ECDH::GetPublicKey(const FunctionCallbackInfo<Value>& args) {
if (size == 0)
return env->ThrowError("Failed to get public key length");

unsigned char* out = node::Malloc<unsigned char>(size);
auto* allocator = env->isolate()->GetArrayBufferAllocator();
unsigned char* out =
static_cast<unsigned char*>(allocator->AllocateUninitialized(size));

int r = EC_POINT_point2oct(ecdh->group_, pub, form, out, size, nullptr);
if (r != size) {
free(out);
allocator->Free(out, size);
return env->ThrowError("Failed to get public key");
}

Expand All @@ -5399,11 +5414,13 @@ void ECDH::GetPrivateKey(const FunctionCallbackInfo<Value>& args) {
if (b == nullptr)
return env->ThrowError("Failed to get ECDH private key");

auto* allocator = env->isolate()->GetArrayBufferAllocator();
int size = BN_num_bytes(b);
unsigned char* out = node::Malloc<unsigned char>(size);
unsigned char* out =
static_cast<unsigned char*>(allocator->AllocateUninitialized(size));

if (size != BN_bn2bin(b, out)) {
free(out);
allocator->Free(out, size);
return env->ThrowError("Failed to convert ECDH private key to Buffer");
}

Expand Down Expand Up @@ -5532,7 +5549,8 @@ class PBKDF2Request : public AsyncWrap {
saltlen_(saltlen),
salt_(salt),
keylen_(keylen),
key_(node::Malloc(keylen)),
key_(static_cast<char*>(env->isolate()->GetArrayBufferAllocator()->
AllocateUninitialized(keylen))),
iter_(iter) {
Wrap(object, this);
}
Expand All @@ -5546,7 +5564,7 @@ class PBKDF2Request : public AsyncWrap {
salt_ = nullptr;
saltlen_ = 0;

free(key_);
env()->isolate()->GetArrayBufferAllocator()->Free(key_, keylen_);
key_ = nullptr;
keylen_ = 0;

Expand Down Expand Up @@ -5738,9 +5756,10 @@ class RandomBytesRequest : public AsyncWrap {
}

inline void release() {
size_t free_size = size_;
size_ = 0;
if (free_mode_ == FREE_DATA) {
free(data_);
env()->isolate()->GetArrayBufferAllocator()->Free(data_, free_size);
data_ = nullptr;
}
}
Expand Down Expand Up @@ -5857,7 +5876,8 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {

Local<Object> obj = env->randombytes_constructor_template()->
NewInstance(env->context()).ToLocalChecked();
char* data = node::Malloc(size);
char* data = static_cast<char*>(
env->isolate()->GetArrayBufferAllocator()->AllocateUninitialized(size));
std::unique_ptr<RandomBytesRequest> req(
new RandomBytesRequest(env,
obj,
Expand Down Expand Up @@ -6057,10 +6077,11 @@ void VerifySpkac(const FunctionCallbackInfo<Value>& args) {
}


char* ExportPublicKey(const char* data, int len, size_t* size) {
char* ExportPublicKey(Environment* env, const char* data, int len, size_t* size) {
char* buf = nullptr;
EVP_PKEY* pkey = nullptr;
NETSCAPE_SPKI* spki = nullptr;
auto* allocator = env->isolate()->GetArrayBufferAllocator();

BIO* bio = BIO_new(BIO_s_mem());
if (bio == nullptr)
Expand All @@ -6081,7 +6102,7 @@ char* ExportPublicKey(const char* data, int len, size_t* size) {
BIO_get_mem_ptr(bio, &ptr);

*size = ptr->length;
buf = Malloc(*size);
buf = static_cast<char*>(allocator->AllocateUninitialized(*size));
memcpy(buf, ptr->data, *size);

exit:
Expand Down Expand Up @@ -6109,7 +6130,7 @@ void ExportPublicKey(const FunctionCallbackInfo<Value>& args) {
CHECK_NE(data, nullptr);

size_t pkey_size;
char* pkey = ExportPublicKey(data, length, &pkey_size);
char* pkey = ExportPublicKey(env, data, length, &pkey_size);
if (pkey == nullptr)
return args.GetReturnValue().SetEmptyString();

Expand Down
3 changes: 2 additions & 1 deletion src/node_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,8 @@ class PublicKeyCipher {
template <Operation operation,
EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
EVP_PKEY_cipher_t EVP_PKEY_cipher>
static bool Cipher(const char* key_pem,
static bool Cipher(Environment* env,
const char* key_pem,
int key_pem_len,
const char* passphrase,
int padding,
Expand Down
11 changes: 9 additions & 2 deletions src/stream_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -347,19 +347,26 @@ void StreamResource::ClearError() {


uv_buf_t StreamListener::OnStreamAlloc(size_t suggested_size) {
return uv_buf_init(Malloc(suggested_size), suggested_size);
CHECK_NE(stream_, nullptr);
StreamBase* stream = static_cast<StreamBase*>(stream_);
Environment* env = stream->stream_env();
auto* allocator = env->isolate()->GetArrayBufferAllocator();
return uv_buf_init(
static_cast<char*>(allocator->AllocateUninitialized(suggested_size)),
suggested_size);
}


void EmitToJSStreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
CHECK_NE(stream_, nullptr);
StreamBase* stream = static_cast<StreamBase*>(stream_);
Environment* env = stream->stream_env();
auto* allocator = env->isolate()->GetArrayBufferAllocator();
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());

if (nread <= 0) {
free(buf.base);
allocator->Free(buf.base, buf.len);
if (nread < 0)
stream->CallJSOnreadMethod(nread, Local<Object>());
return;
Expand Down
Loading

0 comments on commit 813a45f

Please sign in to comment.