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

Commit cbbe8e8

Browse files
zcbenzalexeykuzmin
authored andcommitted
Allocate memory of Buffer with V8's allocator
(cherry picked from commit 813a45f)
1 parent 16db0ee commit cbbe8e8

File tree

5 files changed

+86
-48
lines changed

5 files changed

+86
-48
lines changed

src/node_buffer.cc

+14-11
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ bool zero_fill_all_buffers = false;
6161

6262
namespace {
6363

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

6970
} // namespace
@@ -241,7 +242,7 @@ MaybeLocal<Object> New(Isolate* isolate,
241242
char* data = nullptr;
242243

243244
if (length > 0) {
244-
data = static_cast<char*>(BufferMalloc(length));
245+
data = static_cast<char*>(BufferMalloc(isolate, length));
245246

246247
if (data == nullptr)
247248
return Local<Object>();
@@ -250,10 +251,11 @@ MaybeLocal<Object> New(Isolate* isolate,
250251
CHECK(actual <= length);
251252

252253
if (actual == 0) {
253-
free(data);
254+
isolate->GetArrayBufferAllocator()->Free(data, length);
254255
data = nullptr;
255256
} else if (actual < length) {
256-
data = node::Realloc(data, actual);
257+
// We should call realloc here, but v8::ArrayBufferAllocator does not
258+
// provide such ability.
257259
}
258260
}
259261

@@ -262,7 +264,7 @@ MaybeLocal<Object> New(Isolate* isolate,
262264
return scope.Escape(buf);
263265

264266
// Object failed to be created. Clean up resources.
265-
free(data);
267+
isolate->GetArrayBufferAllocator()->Free(data, length);
266268
return Local<Object>();
267269
}
268270

@@ -286,7 +288,7 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
286288

287289
void* data;
288290
if (length > 0) {
289-
data = BufferMalloc(length);
291+
data = BufferMalloc(env->isolate(), length);
290292
if (data == nullptr)
291293
return Local<Object>();
292294
} else {
@@ -302,7 +304,7 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
302304

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

308310
return scope.Escape(ui.FromMaybe(Local<Uint8Array>()));
@@ -327,10 +329,11 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
327329
return Local<Object>();
328330
}
329331

332+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
330333
void* new_data;
331334
if (length > 0) {
332335
CHECK_NE(data, nullptr);
333-
new_data = node::UncheckedMalloc(length);
336+
new_data = allocator->AllocateUninitialized(length);
334337
if (new_data == nullptr)
335338
return Local<Object>();
336339
memcpy(new_data, data, length);
@@ -347,7 +350,7 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
347350

348351
if (ui.IsEmpty()) {
349352
// Object failed to be created. Clean up resources.
350-
free(new_data);
353+
allocator->Free(new_data, length);
351354
}
352355

353356
return scope.Escape(ui.FromMaybe(Local<Uint8Array>()));

src/node_crypto.cc

+47-26
Original file line numberDiff line numberDiff line change
@@ -1937,7 +1937,8 @@ void SSLWrap<Base>::GetSession(const FunctionCallbackInfo<Value>& args) {
19371937
int slen = i2d_SSL_SESSION(sess, nullptr);
19381938
CHECK_GT(slen, 0);
19391939

1940-
char* sbuf = Malloc(slen);
1940+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
1941+
char* sbuf = static_cast<char*>(allocator->AllocateUninitialized(slen));
19411942
unsigned char* p = reinterpret_cast<unsigned char*>(sbuf);
19421943
i2d_SSL_SESSION(sess, &p);
19431944
args.GetReturnValue().Set(Buffer::New(env, sbuf, slen).ToLocalChecked());
@@ -3000,8 +3001,9 @@ CipherBase::UpdateResult CipherBase::Update(const char* data,
30003001
auth_tag_set_ = true;
30013002
}
30023003

3004+
auto* allocator = env()->isolate()->GetArrayBufferAllocator();
30033005
*out_len = len + EVP_CIPHER_CTX_block_size(ctx_);
3004-
*out = Malloc<unsigned char>(static_cast<size_t>(*out_len));
3006+
*out = static_cast<unsigned char*>(allocator->AllocateUninitialized(*out_len));
30053007
int r = EVP_CipherUpdate(ctx_,
30063008
*out,
30073009
out_len,
@@ -3041,7 +3043,8 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
30413043
}
30423044

30433045
if (r != kSuccess) {
3044-
free(out);
3046+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
3047+
allocator->Free(out, out_len);
30453048
if (r == kErrorState) {
30463049
ThrowCryptoError(env, ERR_get_error(),
30473050
"Trying to add data in unsupported state");
@@ -3079,8 +3082,9 @@ bool CipherBase::Final(unsigned char** out, int *out_len) {
30793082

30803083
const int mode = EVP_CIPHER_CTX_mode(ctx_);
30813084

3082-
*out = Malloc<unsigned char>(
3083-
static_cast<size_t>(EVP_CIPHER_CTX_block_size(ctx_)));
3085+
auto* allocator = env()->isolate()->GetArrayBufferAllocator();
3086+
*out = static_cast<unsigned char*>(allocator->AllocateUninitialized(
3087+
EVP_CIPHER_CTX_block_size(ctx_)));
30843088

30853089
// In CCM mode, final() only checks whether authentication failed in update().
30863090
// EVP_CipherFinal_ex must not be called and will fail.
@@ -3125,7 +3129,8 @@ void CipherBase::Final(const FunctionCallbackInfo<Value>& args) {
31253129
bool r = cipher->Final(&out_value, &out_len);
31263130

31273131
if (out_len <= 0 || !r) {
3128-
free(out_value);
3132+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
3133+
allocator->Free(out_value, out_len);
31293134
out_value = nullptr;
31303135
out_len = 0;
31313136
if (!r) {
@@ -3837,7 +3842,8 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
38373842
template <PublicKeyCipher::Operation operation,
38383843
PublicKeyCipher::EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
38393844
PublicKeyCipher::EVP_PKEY_cipher_t EVP_PKEY_cipher>
3840-
bool PublicKeyCipher::Cipher(const char* key_pem,
3845+
bool PublicKeyCipher::Cipher(Environment* env,
3846+
const char* key_pem,
38413847
int key_pem_len,
38423848
const char* passphrase,
38433849
int padding,
@@ -3850,6 +3856,7 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
38503856
BIO* bp = nullptr;
38513857
X509* x509 = nullptr;
38523858
bool fatal = true;
3859+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
38533860

38543861
bp = BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len);
38553862
if (bp == nullptr)
@@ -3902,7 +3909,7 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
39023909
if (EVP_PKEY_cipher(ctx, nullptr, out_len, data, len) <= 0)
39033910
goto exit;
39043911

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

39073914
if (EVP_PKEY_cipher(ctx, *out, out_len, data, len) <= 0)
39083915
goto exit;
@@ -3947,6 +3954,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
39473954
ClearErrorOnReturn clear_error_on_return;
39483955

39493956
bool r = Cipher<operation, EVP_PKEY_cipher_init, EVP_PKEY_cipher>(
3957+
env,
39503958
kbuf,
39513959
klen,
39523960
args.Length() >= 3 && !args[2]->IsNull() ? *passphrase : nullptr,
@@ -3957,7 +3965,8 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
39573965
&out_len);
39583966

39593967
if (out_len == 0 || !r) {
3960-
free(out_value);
3968+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
3969+
allocator->Free(out_value, out_len);
39613970
out_value = nullptr;
39623971
out_len = 0;
39633972
if (!r) {
@@ -4162,7 +4171,8 @@ void DiffieHellman::GenerateKeys(const FunctionCallbackInfo<Value>& args) {
41624171
const BIGNUM* pub_key;
41634172
DH_get0_key(diffieHellman->dh, &pub_key, nullptr);
41644173
size_t size = BN_num_bytes(pub_key);
4165-
char* data = Malloc(size);
4174+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
4175+
char* data = static_cast<char*>(allocator->AllocateUninitialized(size));
41664176
BN_bn2bin(pub_key, reinterpret_cast<unsigned char*>(data));
41674177
args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked());
41684178
}
@@ -4181,7 +4191,8 @@ void DiffieHellman::GetField(const FunctionCallbackInfo<Value>& args,
41814191
if (num == nullptr) return env->ThrowError(err_if_null);
41824192

41834193
size_t size = BN_num_bytes(num);
4184-
char* data = Malloc(size);
4194+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
4195+
char* data = static_cast<char*>(allocator->AllocateUninitialized(size));
41854196
BN_bn2bin(num, reinterpret_cast<unsigned char*>(data));
41864197
args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked());
41874198
}
@@ -4247,7 +4258,8 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
42474258
}
42484259

42494260
int dataSize = DH_size(diffieHellman->dh);
4250-
char* data = Malloc(dataSize);
4261+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
4262+
char* data = static_cast<char*>(allocator->AllocateUninitialized(dataSize));
42514263

42524264
int size = DH_compute_key(reinterpret_cast<unsigned char*>(data),
42534265
key,
@@ -4259,7 +4271,7 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
42594271

42604272
checked = DH_check_pub_key(diffieHellman->dh, key, &checkResult);
42614273
BN_free(key);
4262-
free(data);
4274+
allocator->Free(data, dataSize);
42634275

42644276
if (!checked) {
42654277
return ThrowCryptoError(env, ERR_get_error(), "Invalid Key");
@@ -4470,14 +4482,15 @@ void ECDH::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
44704482
}
44714483

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

44774490
int r = ECDH_compute_key(out, out_len, pub, ecdh->key_, nullptr);
44784491
EC_POINT_free(pub);
44794492
if (!r) {
4480-
free(out);
4493+
allocator->Free(out, out_len);
44814494
return env->ThrowError("Failed to compute ECDH key");
44824495
}
44834496

@@ -4507,11 +4520,13 @@ void ECDH::GetPublicKey(const FunctionCallbackInfo<Value>& args) {
45074520
if (size == 0)
45084521
return env->ThrowError("Failed to get public key length");
45094522

4510-
unsigned char* out = node::Malloc<unsigned char>(size);
4523+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
4524+
unsigned char* out =
4525+
static_cast<unsigned char*>(allocator->AllocateUninitialized(size));
45114526

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

@@ -4531,11 +4546,13 @@ void ECDH::GetPrivateKey(const FunctionCallbackInfo<Value>& args) {
45314546
if (b == nullptr)
45324547
return env->ThrowError("Failed to get ECDH private key");
45334548

4549+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
45344550
int size = BN_num_bytes(b);
4535-
unsigned char* out = node::Malloc<unsigned char>(size);
4551+
unsigned char* out =
4552+
static_cast<unsigned char*>(allocator->AllocateUninitialized(size));
45364553

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

@@ -4666,7 +4683,8 @@ class PBKDF2Request : public AsyncWrap {
46664683
saltlen_(saltlen),
46674684
salt_(salt),
46684685
keylen_(keylen),
4669-
key_(node::Malloc(keylen)),
4686+
key_(static_cast<char*>(env->isolate()->GetArrayBufferAllocator()->
4687+
AllocateUninitialized(keylen))),
46704688
iter_(iter) {
46714689
Wrap(object, this);
46724690
}
@@ -4680,7 +4698,7 @@ class PBKDF2Request : public AsyncWrap {
46804698
salt_ = nullptr;
46814699
saltlen_ = 0;
46824700

4683-
free(key_);
4701+
env()->isolate()->GetArrayBufferAllocator()->Free(key_, keylen_);
46844702
key_ = nullptr;
46854703
keylen_ = 0;
46864704

@@ -4870,9 +4888,10 @@ class RandomBytesRequest : public AsyncWrap {
48704888
}
48714889

48724890
inline void release() {
4891+
size_t free_size = size_;
48734892
size_ = 0;
48744893
if (free_mode_ == FREE_DATA) {
4875-
free(data_);
4894+
env()->isolate()->GetArrayBufferAllocator()->Free(data_, free_size);
48764895
data_ = nullptr;
48774896
}
48784897
}
@@ -4989,7 +5008,8 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
49895008

49905009
Local<Object> obj = env->randombytes_constructor_template()->
49915010
NewInstance(env->context()).ToLocalChecked();
4992-
char* data = node::Malloc(size);
5011+
char* data = static_cast<char*>(
5012+
env->isolate()->GetArrayBufferAllocator()->AllocateUninitialized(size));
49935013
std::unique_ptr<RandomBytesRequest> req(
49945014
new RandomBytesRequest(env,
49955015
obj,
@@ -5189,10 +5209,11 @@ void VerifySpkac(const FunctionCallbackInfo<Value>& args) {
51895209
}
51905210

51915211

5192-
char* ExportPublicKey(const char* data, int len, size_t* size) {
5212+
char* ExportPublicKey(Environment* env, const char* data, int len, size_t* size) {
51935213
char* buf = nullptr;
51945214
EVP_PKEY* pkey = nullptr;
51955215
NETSCAPE_SPKI* spki = nullptr;
5216+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
51965217

51975218
BIO* bio = BIO_new(BIO_s_mem());
51985219
if (bio == nullptr)
@@ -5213,7 +5234,7 @@ char* ExportPublicKey(const char* data, int len, size_t* size) {
52135234
BIO_get_mem_ptr(bio, &ptr);
52145235

52155236
*size = ptr->length;
5216-
buf = Malloc(*size);
5237+
buf = static_cast<char*>(allocator->AllocateUninitialized(*size));
52175238
memcpy(buf, ptr->data, *size);
52185239

52195240
exit:
@@ -5241,7 +5262,7 @@ void ExportPublicKey(const FunctionCallbackInfo<Value>& args) {
52415262
CHECK_NE(data, nullptr);
52425263

52435264
size_t pkey_size;
5244-
char* pkey = ExportPublicKey(data, length, &pkey_size);
5265+
char* pkey = ExportPublicKey(env, data, length, &pkey_size);
52455266
if (pkey == nullptr)
52465267
return args.GetReturnValue().SetEmptyString();
52475268

src/node_crypto.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,8 @@ class PublicKeyCipher {
553553
template <Operation operation,
554554
EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
555555
EVP_PKEY_cipher_t EVP_PKEY_cipher>
556-
static bool Cipher(const char* key_pem,
556+
static bool Cipher(Environment* env,
557+
const char* key_pem,
557558
int key_pem_len,
558559
const char* passphrase,
559560
int padding,

src/stream_base.cc

+9-2
Original file line numberDiff line numberDiff line change
@@ -361,19 +361,26 @@ void StreamResource::ClearError() {
361361

362362

363363
uv_buf_t StreamListener::OnStreamAlloc(size_t suggested_size) {
364-
return uv_buf_init(Malloc(suggested_size), suggested_size);
364+
CHECK_NE(stream_, nullptr);
365+
StreamBase* stream = static_cast<StreamBase*>(stream_);
366+
Environment* env = stream->stream_env();
367+
auto* allocator = env->isolate()->GetArrayBufferAllocator();
368+
return uv_buf_init(
369+
static_cast<char*>(allocator->AllocateUninitialized(suggested_size)),
370+
suggested_size);
365371
}
366372

367373

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

375382
if (nread <= 0) {
376-
free(buf.base);
383+
allocator->Free(buf.base, buf.len);
377384
if (nread < 0)
378385
stream->CallJSOnreadMethod(nread, Local<Object>());
379386
return;

0 commit comments

Comments
 (0)