diff --git a/src/node_buffer.cc b/src/node_buffer.cc index dff9d3c0995..a8e981d7a3f 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -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 @@ -246,7 +247,7 @@ MaybeLocal New(Isolate* isolate, char* data = nullptr; if (length > 0) { - data = static_cast(BufferMalloc(length)); + data = static_cast(BufferMalloc(isolate, length)); if (data == nullptr) return Local(); @@ -255,10 +256,11 @@ MaybeLocal 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. } } @@ -267,7 +269,7 @@ MaybeLocal New(Isolate* isolate, return scope.Escape(buf); // Object failed to be created. Clean up resources. - free(data); + isolate->GetArrayBufferAllocator()->Free(data, length); return Local(); } @@ -291,7 +293,7 @@ MaybeLocal New(Environment* env, size_t length) { void* data; if (length > 0) { - data = BufferMalloc(length); + data = BufferMalloc(env->isolate(), length); if (data == nullptr) return Local(); } else { @@ -307,7 +309,7 @@ MaybeLocal 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())); @@ -332,10 +334,11 @@ MaybeLocal Copy(Environment* env, const char* data, size_t length) { return Local(); } + 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(); memcpy(new_data, data, length); @@ -352,7 +355,7 @@ MaybeLocal 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())); diff --git a/src/node_crypto.cc b/src/node_crypto.cc index a398f745537..d5cc8706cf6 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -2114,7 +2114,8 @@ void SSLWrap::GetSession(const FunctionCallbackInfo& 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(allocator->AllocateUninitialized(slen)); unsigned char* p = reinterpret_cast(sbuf); i2d_SSL_SESSION(sess, &p); args.GetReturnValue().Set(Buffer::New(env, sbuf, slen).ToLocalChecked()); @@ -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(static_cast(*out_len)); + *out = static_cast(allocator->AllocateUninitialized(*out_len)); return EVP_CipherUpdate(ctx_, *out, out_len, @@ -3929,7 +3931,8 @@ void CipherBase::Update(const FunctionCallbackInfo& 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"); @@ -3965,8 +3968,9 @@ bool CipherBase::Final(unsigned char** out, int *out_len) { if (ctx_ == nullptr) return false; - *out = Malloc( - static_cast(EVP_CIPHER_CTX_block_size(ctx_))); + auto* allocator = env()->isolate()->GetArrayBufferAllocator(); + *out = static_cast(allocator->AllocateUninitialized( + EVP_CIPHER_CTX_block_size(ctx_))); int r = EVP_CipherFinal_ex(ctx_, *out, out_len); if (r == 1 && kind_ == kCipher && IsAuthenticatedMode()) { @@ -3998,7 +4002,8 @@ void CipherBase::Final(const FunctionCallbackInfo& 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) { @@ -4712,7 +4717,8 @@ void Verify::VerifyFinal(const FunctionCallbackInfo& args) { template -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, @@ -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(key_pem), key_pem_len); if (bp == nullptr) @@ -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(*out_len); + *out = static_cast(allocator->AllocateUninitialized(*out_len)); if (EVP_PKEY_cipher(ctx, *out, out_len, data, len) <= 0) goto exit; @@ -4822,6 +4829,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo& args) { ClearErrorOnReturn clear_error_on_return; bool r = Cipher( + env, kbuf, klen, args.Length() >= 3 && !args[2]->IsNull() ? *passphrase : nullptr, @@ -4832,7 +4840,8 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo& 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) { @@ -5037,7 +5046,8 @@ void DiffieHellman::GenerateKeys(const FunctionCallbackInfo& 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(allocator->AllocateUninitialized(size)); BN_bn2bin(pub_key, reinterpret_cast(data)); args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked()); } @@ -5056,7 +5066,8 @@ void DiffieHellman::GetField(const FunctionCallbackInfo& 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(allocator->AllocateUninitialized(size)); BN_bn2bin(num, reinterpret_cast(data)); args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked()); } @@ -5121,7 +5132,8 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo& args) { } int dataSize = DH_size(diffieHellman->dh); - char* data = Malloc(dataSize); + auto* allocator = env->isolate()->GetArrayBufferAllocator(); + char* data = static_cast(allocator->AllocateUninitialized(dataSize)); int size = DH_compute_key(reinterpret_cast(data), key, @@ -5133,7 +5145,7 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo& 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"); @@ -5338,14 +5350,15 @@ void ECDH::ComputeSecret(const FunctionCallbackInfo& 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(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"); } @@ -5375,11 +5388,13 @@ void ECDH::GetPublicKey(const FunctionCallbackInfo& args) { if (size == 0) return env->ThrowError("Failed to get public key length"); - unsigned char* out = node::Malloc(size); + auto* allocator = env->isolate()->GetArrayBufferAllocator(); + unsigned char* out = + static_cast(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"); } @@ -5399,11 +5414,13 @@ void ECDH::GetPrivateKey(const FunctionCallbackInfo& 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(size); + unsigned char* out = + static_cast(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"); } @@ -5532,7 +5549,8 @@ class PBKDF2Request : public AsyncWrap { saltlen_(saltlen), salt_(salt), keylen_(keylen), - key_(node::Malloc(keylen)), + key_(static_cast(env->isolate()->GetArrayBufferAllocator()-> + AllocateUninitialized(keylen))), iter_(iter) { Wrap(object, this); } @@ -5546,7 +5564,7 @@ class PBKDF2Request : public AsyncWrap { salt_ = nullptr; saltlen_ = 0; - free(key_); + env()->isolate()->GetArrayBufferAllocator()->Free(key_, keylen_); key_ = nullptr; keylen_ = 0; @@ -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; } } @@ -5857,7 +5876,8 @@ void RandomBytes(const FunctionCallbackInfo& args) { Local obj = env->randombytes_constructor_template()-> NewInstance(env->context()).ToLocalChecked(); - char* data = node::Malloc(size); + char* data = static_cast( + env->isolate()->GetArrayBufferAllocator()->AllocateUninitialized(size)); std::unique_ptr req( new RandomBytesRequest(env, obj, @@ -6057,10 +6077,11 @@ void VerifySpkac(const FunctionCallbackInfo& 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) @@ -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(allocator->AllocateUninitialized(*size)); memcpy(buf, ptr->data, *size); exit: @@ -6109,7 +6130,7 @@ void ExportPublicKey(const FunctionCallbackInfo& 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(); diff --git a/src/node_crypto.h b/src/node_crypto.h index b866117f844..d5ea77191d1 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -640,7 +640,8 @@ class PublicKeyCipher { template - 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, diff --git a/src/stream_base.cc b/src/stream_base.cc index 9ad9fd5bcb4..5a1c791634c 100644 --- a/src/stream_base.cc +++ b/src/stream_base.cc @@ -347,7 +347,13 @@ 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(stream_); + Environment* env = stream->stream_env(); + auto* allocator = env->isolate()->GetArrayBufferAllocator(); + return uv_buf_init( + static_cast(allocator->AllocateUninitialized(suggested_size)), + suggested_size); } @@ -355,11 +361,12 @@ void EmitToJSStreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf) { CHECK_NE(stream_, nullptr); StreamBase* stream = static_cast(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()); return; diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 0d7a048a7d7..a621273f549 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -459,7 +459,10 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) { void UDPWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - buf->base = node::Malloc(suggested_size); + auto* wrap = static_cast(handle->data); + auto* allocator = wrap->env()->isolate()->GetArrayBufferAllocator(); + buf->base = + static_cast(allocator->AllocateUninitialized(suggested_size)); buf->len = suggested_size; } @@ -469,15 +472,16 @@ void UDPWrap::OnRecv(uv_udp_t* handle, const uv_buf_t* buf, const struct sockaddr* addr, unsigned int flags) { + UDPWrap* wrap = static_cast(handle->data); + Environment* env = wrap->env(); + auto* allocator = env->isolate()->GetArrayBufferAllocator(); + if (nread == 0 && addr == nullptr) { if (buf->base != nullptr) - free(buf->base); + allocator->Free(buf->base, buf->len); return; } - UDPWrap* wrap = static_cast(handle->data); - Environment* env = wrap->env(); - HandleScope handle_scope(env->isolate()); Context::Scope context_scope(env->context()); @@ -491,13 +495,15 @@ void UDPWrap::OnRecv(uv_udp_t* handle, if (nread < 0) { if (buf->base != nullptr) - free(buf->base); + allocator->Free(buf->base, buf->len); wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv); return; } - char* base = node::UncheckedRealloc(buf->base, nread); - argv[2] = Buffer::New(env, base, nread).ToLocalChecked(); + // Note that nread may be smaller thant buf->len, in that case the length + // passed to ArrayBufferAllocator::Free would not be the correct one, but + // it should be fine unless embedder is using some unusual memory allocator. + argv[2] = Buffer::New(env, buf->base, nread).ToLocalChecked(); argv[3] = AddressToJS(env, addr); wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv); }