Allocate memory of Buffer with V8's allocator
(cherry picked from commit 813a45f791
)
(cherry picked from commit cbbe8e8722c72355d2ac25e918e57d413e846c1a)
This commit is contained in:
Родитель
201f3b6684
Коммит
f61bae3440
|
@ -61,9 +61,10 @@ bool zero_fill_all_buffers = false;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
inline void* BufferMalloc(size_t length) {
|
inline void* BufferMalloc(v8::Isolate* isolate, size_t length) {
|
||||||
return zero_fill_all_buffers ? node::UncheckedCalloc(length) :
|
auto* allocator = isolate->GetArrayBufferAllocator();
|
||||||
node::UncheckedMalloc(length);
|
return zero_fill_all_buffers ? allocator->Allocate(length) :
|
||||||
|
allocator->AllocateUninitialized(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -241,7 +242,7 @@ MaybeLocal<Object> New(Isolate* isolate,
|
||||||
char* data = nullptr;
|
char* data = nullptr;
|
||||||
|
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
data = static_cast<char*>(BufferMalloc(length));
|
data = static_cast<char*>(BufferMalloc(isolate, length));
|
||||||
|
|
||||||
if (data == nullptr)
|
if (data == nullptr)
|
||||||
return Local<Object>();
|
return Local<Object>();
|
||||||
|
@ -250,10 +251,11 @@ MaybeLocal<Object> New(Isolate* isolate,
|
||||||
CHECK(actual <= length);
|
CHECK(actual <= length);
|
||||||
|
|
||||||
if (actual == 0) {
|
if (actual == 0) {
|
||||||
free(data);
|
isolate->GetArrayBufferAllocator()->Free(data, length);
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
} else if (actual < length) {
|
} else if (actual < length) {
|
||||||
data = node::Realloc(data, actual);
|
// We should call realloc here, but v8::ArrayBufferAllocator does not
|
||||||
|
// provide such ability.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +264,7 @@ MaybeLocal<Object> New(Isolate* isolate,
|
||||||
return scope.Escape(buf);
|
return scope.Escape(buf);
|
||||||
|
|
||||||
// Object failed to be created. Clean up resources.
|
// Object failed to be created. Clean up resources.
|
||||||
free(data);
|
isolate->GetArrayBufferAllocator()->Free(data, length);
|
||||||
return Local<Object>();
|
return Local<Object>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +288,7 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
|
||||||
|
|
||||||
void* data;
|
void* data;
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
data = BufferMalloc(length);
|
data = BufferMalloc(env->isolate(), length);
|
||||||
if (data == nullptr)
|
if (data == nullptr)
|
||||||
return Local<Object>();
|
return Local<Object>();
|
||||||
} else {
|
} else {
|
||||||
|
@ -302,7 +304,7 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
|
||||||
|
|
||||||
if (ui.IsEmpty()) {
|
if (ui.IsEmpty()) {
|
||||||
// Object failed to be created. Clean up resources.
|
// Object failed to be created. Clean up resources.
|
||||||
free(data);
|
env->isolate()->GetArrayBufferAllocator()->Free(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return scope.Escape(ui.FromMaybe(Local<Uint8Array>()));
|
return scope.Escape(ui.FromMaybe(Local<Uint8Array>()));
|
||||||
|
@ -327,10 +329,11 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
|
||||||
return Local<Object>();
|
return Local<Object>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
void* new_data;
|
void* new_data;
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
CHECK_NE(data, nullptr);
|
CHECK_NE(data, nullptr);
|
||||||
new_data = node::UncheckedMalloc(length);
|
new_data = allocator->AllocateUninitialized(length);
|
||||||
if (new_data == nullptr)
|
if (new_data == nullptr)
|
||||||
return Local<Object>();
|
return Local<Object>();
|
||||||
memcpy(new_data, data, length);
|
memcpy(new_data, data, length);
|
||||||
|
@ -347,7 +350,7 @@ MaybeLocal<Object> Copy(Environment* env, const char* data, size_t length) {
|
||||||
|
|
||||||
if (ui.IsEmpty()) {
|
if (ui.IsEmpty()) {
|
||||||
// Object failed to be created. Clean up resources.
|
// Object failed to be created. Clean up resources.
|
||||||
free(new_data);
|
allocator->Free(new_data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return scope.Escape(ui.FromMaybe(Local<Uint8Array>()));
|
return scope.Escape(ui.FromMaybe(Local<Uint8Array>()));
|
||||||
|
|
|
@ -1890,7 +1890,8 @@ void SSLWrap<Base>::GetSession(const FunctionCallbackInfo<Value>& args) {
|
||||||
int slen = i2d_SSL_SESSION(sess, nullptr);
|
int slen = i2d_SSL_SESSION(sess, nullptr);
|
||||||
CHECK_GT(slen, 0);
|
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);
|
unsigned char* p = reinterpret_cast<unsigned char*>(sbuf);
|
||||||
i2d_SSL_SESSION(sess, &p);
|
i2d_SSL_SESSION(sess, &p);
|
||||||
args.GetReturnValue().Set(Buffer::New(env, sbuf, slen).ToLocalChecked());
|
args.GetReturnValue().Set(Buffer::New(env, sbuf, slen).ToLocalChecked());
|
||||||
|
@ -3011,7 +3012,8 @@ CipherBase::UpdateResult CipherBase::Update(const char* data,
|
||||||
return kErrorState;
|
return kErrorState;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = Malloc<unsigned char>(buff_len);
|
auto* allocator = env()->isolate()->GetArrayBufferAllocator();
|
||||||
|
*out = static_cast<unsigned char*>(allocator->AllocateUninitialized(buff_len));
|
||||||
int r = EVP_CipherUpdate(ctx_.get(),
|
int r = EVP_CipherUpdate(ctx_.get(),
|
||||||
*out,
|
*out,
|
||||||
out_len,
|
out_len,
|
||||||
|
@ -3053,7 +3055,8 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r != kSuccess) {
|
if (r != kSuccess) {
|
||||||
free(out);
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
|
allocator->Free(out, out_len);
|
||||||
if (r == kErrorState) {
|
if (r == kErrorState) {
|
||||||
ThrowCryptoError(env, ERR_get_error(),
|
ThrowCryptoError(env, ERR_get_error(),
|
||||||
"Trying to add data in unsupported state");
|
"Trying to add data in unsupported state");
|
||||||
|
@ -3091,8 +3094,9 @@ bool CipherBase::Final(unsigned char** out, int* out_len) {
|
||||||
|
|
||||||
const int mode = EVP_CIPHER_CTX_mode(ctx_.get());
|
const int mode = EVP_CIPHER_CTX_mode(ctx_.get());
|
||||||
|
|
||||||
*out = Malloc<unsigned char>(
|
auto* allocator = env()->isolate()->GetArrayBufferAllocator();
|
||||||
static_cast<size_t>(EVP_CIPHER_CTX_block_size(ctx_.get())));
|
*out = static_cast<unsigned char*>(allocator->AllocateUninitialized(
|
||||||
|
EVP_CIPHER_CTX_block_size(ctx_.get())));
|
||||||
|
|
||||||
// In CCM mode, final() only checks whether authentication failed in update().
|
// In CCM mode, final() only checks whether authentication failed in update().
|
||||||
// EVP_CipherFinal_ex must not be called and will fail.
|
// EVP_CipherFinal_ex must not be called and will fail.
|
||||||
|
@ -3135,7 +3139,8 @@ 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) {
|
||||||
free(out_value);
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
|
allocator->Free(out_value, out_len);
|
||||||
out_value = nullptr;
|
out_value = nullptr;
|
||||||
out_len = 0;
|
out_len = 0;
|
||||||
if (!r) {
|
if (!r) {
|
||||||
|
@ -3781,7 +3786,8 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
|
||||||
template <PublicKeyCipher::Operation operation,
|
template <PublicKeyCipher::Operation operation,
|
||||||
PublicKeyCipher::EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
|
PublicKeyCipher::EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
|
||||||
PublicKeyCipher::EVP_PKEY_cipher_t EVP_PKEY_cipher>
|
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,
|
int key_pem_len,
|
||||||
const char* passphrase,
|
const char* passphrase,
|
||||||
int padding,
|
int padding,
|
||||||
|
@ -3790,6 +3796,7 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
|
||||||
unsigned char** out,
|
unsigned char** out,
|
||||||
size_t* out_len) {
|
size_t* out_len) {
|
||||||
EVPKeyPointer pkey;
|
EVPKeyPointer pkey;
|
||||||
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
|
|
||||||
BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
|
BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
|
||||||
if (!bp)
|
if (!bp)
|
||||||
|
@ -3837,7 +3844,7 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
|
||||||
if (EVP_PKEY_cipher(ctx.get(), nullptr, out_len, data, len) <= 0)
|
if (EVP_PKEY_cipher(ctx.get(), nullptr, out_len, data, len) <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*out = Malloc<unsigned char>(*out_len);
|
*out = static_cast<unsigned char*>(allocator->AllocateUninitialized(*out_len));
|
||||||
|
|
||||||
if (EVP_PKEY_cipher(ctx.get(), *out, out_len, data, len) <= 0)
|
if (EVP_PKEY_cipher(ctx.get(), *out, out_len, data, len) <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
@ -3870,6 +3877,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||||
ClearErrorOnReturn clear_error_on_return;
|
ClearErrorOnReturn clear_error_on_return;
|
||||||
|
|
||||||
bool r = Cipher<operation, EVP_PKEY_cipher_init, EVP_PKEY_cipher>(
|
bool r = Cipher<operation, EVP_PKEY_cipher_init, EVP_PKEY_cipher>(
|
||||||
|
env,
|
||||||
kbuf,
|
kbuf,
|
||||||
klen,
|
klen,
|
||||||
args.Length() >= 3 && !args[2]->IsNull() ? *passphrase : nullptr,
|
args.Length() >= 3 && !args[2]->IsNull() ? *passphrase : nullptr,
|
||||||
|
@ -3880,7 +3888,8 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||||
&out_len);
|
&out_len);
|
||||||
|
|
||||||
if (out_len == 0 || !r) {
|
if (out_len == 0 || !r) {
|
||||||
free(out_value);
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
|
allocator->Free(out_value, out_len);
|
||||||
out_value = nullptr;
|
out_value = nullptr;
|
||||||
out_len = 0;
|
out_len = 0;
|
||||||
if (!r) {
|
if (!r) {
|
||||||
|
@ -4085,7 +4094,8 @@ void DiffieHellman::GenerateKeys(const FunctionCallbackInfo<Value>& args) {
|
||||||
const BIGNUM* pub_key;
|
const BIGNUM* pub_key;
|
||||||
DH_get0_key(diffieHellman->dh_.get(), &pub_key, nullptr);
|
DH_get0_key(diffieHellman->dh_.get(), &pub_key, nullptr);
|
||||||
size_t size = BN_num_bytes(pub_key);
|
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));
|
BN_bn2bin(pub_key, reinterpret_cast<unsigned char*>(data));
|
||||||
args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked());
|
args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked());
|
||||||
}
|
}
|
||||||
|
@ -4104,7 +4114,8 @@ void DiffieHellman::GetField(const FunctionCallbackInfo<Value>& args,
|
||||||
if (num == nullptr) return env->ThrowError(err_if_null);
|
if (num == nullptr) return env->ThrowError(err_if_null);
|
||||||
|
|
||||||
size_t size = BN_num_bytes(num);
|
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));
|
BN_bn2bin(num, reinterpret_cast<unsigned char*>(data));
|
||||||
args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked());
|
args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked());
|
||||||
}
|
}
|
||||||
|
@ -4168,7 +4179,8 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
|
||||||
Buffer::Length(args[0]),
|
Buffer::Length(args[0]),
|
||||||
0));
|
0));
|
||||||
|
|
||||||
MallocedBuffer<char> data(DH_size(diffieHellman->dh_.get()));
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
|
MallocedBuffer<char> data(DH_size(diffieHellman->dh_.get()), allocator);
|
||||||
|
|
||||||
int size = DH_compute_key(reinterpret_cast<unsigned char*>(data.data),
|
int size = DH_compute_key(reinterpret_cast<unsigned char*>(data.data),
|
||||||
key.get(),
|
key.get(),
|
||||||
|
@ -4388,13 +4400,14 @@ void ECDH::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: field_size is in bits
|
// NOTE: field_size is in bits
|
||||||
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
int field_size = EC_GROUP_get_degree(ecdh->group_);
|
int field_size = EC_GROUP_get_degree(ecdh->group_);
|
||||||
size_t out_len = (field_size + 7) / 8;
|
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.get(), ecdh->key_.get(), nullptr);
|
int r = ECDH_compute_key(out, out_len, pub.get(), ecdh->key_.get(), nullptr);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
free(out);
|
allocator->Free(out, out_len);
|
||||||
return env->ThrowError("Failed to compute ECDH key");
|
return env->ThrowError("Failed to compute ECDH key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4424,11 +4437,13 @@ void ECDH::GetPublicKey(const FunctionCallbackInfo<Value>& args) {
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return env->ThrowError("Failed to get public key length");
|
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);
|
int r = EC_POINT_point2oct(ecdh->group_, pub, form, out, size, nullptr);
|
||||||
if (r != size) {
|
if (r != size) {
|
||||||
free(out);
|
allocator->Free(out, size);
|
||||||
return env->ThrowError("Failed to get public key");
|
return env->ThrowError("Failed to get public key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4448,11 +4463,13 @@ void ECDH::GetPrivateKey(const FunctionCallbackInfo<Value>& args) {
|
||||||
if (b == nullptr)
|
if (b == nullptr)
|
||||||
return env->ThrowError("Failed to get ECDH private key");
|
return env->ThrowError("Failed to get ECDH private key");
|
||||||
|
|
||||||
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
int size = BN_num_bytes(b);
|
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)) {
|
if (size != BN_bn2bin(b, out)) {
|
||||||
free(out);
|
allocator->Free(out, size);
|
||||||
return env->ThrowError("Failed to convert ECDH private key to Buffer");
|
return env->ThrowError("Failed to convert ECDH private key to Buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4572,7 +4589,7 @@ class PBKDF2Request : public AsyncWrap, public ThreadPoolWork {
|
||||||
success_(false),
|
success_(false),
|
||||||
pass_(std::move(pass)),
|
pass_(std::move(pass)),
|
||||||
salt_(std::move(salt)),
|
salt_(std::move(salt)),
|
||||||
key_(keylen),
|
key_(keylen, env->isolate()->GetArrayBufferAllocator()),
|
||||||
iteration_count_(iteration_count) {
|
iteration_count_(iteration_count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4634,6 +4651,7 @@ void PBKDF2Request::AfterThreadPoolWork(int status) {
|
||||||
|
|
||||||
void PBKDF2(const FunctionCallbackInfo<Value>& args) {
|
void PBKDF2(const FunctionCallbackInfo<Value>& args) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
|
|
||||||
const EVP_MD* digest = nullptr;
|
const EVP_MD* digest = nullptr;
|
||||||
int keylen = -1;
|
int keylen = -1;
|
||||||
|
@ -4642,12 +4660,12 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
|
||||||
int passlen = Buffer::Length(args[0]);
|
int passlen = Buffer::Length(args[0]);
|
||||||
|
|
||||||
MallocedBuffer<char> pass(passlen);
|
MallocedBuffer<char> pass(passlen, allocator);
|
||||||
memcpy(pass.data, Buffer::Data(args[0]), passlen);
|
memcpy(pass.data, Buffer::Data(args[0]), passlen);
|
||||||
|
|
||||||
int saltlen = Buffer::Length(args[1]);
|
int saltlen = Buffer::Length(args[1]);
|
||||||
|
|
||||||
MallocedBuffer<char> salt(saltlen);
|
MallocedBuffer<char> salt(saltlen, allocator);
|
||||||
memcpy(salt.data, Buffer::Data(args[1]), saltlen);
|
memcpy(salt.data, Buffer::Data(args[1]), saltlen);
|
||||||
|
|
||||||
iteration_count = args[2]->Int32Value(env->context()).FromJust();
|
iteration_count = args[2]->Int32Value(env->context()).FromJust();
|
||||||
|
@ -4724,9 +4742,10 @@ class RandomBytesRequest : public AsyncWrap, public ThreadPoolWork {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void release() {
|
inline void release() {
|
||||||
|
size_t free_size = size_;
|
||||||
size_ = 0;
|
size_ = 0;
|
||||||
if (free_mode_ == FREE_DATA) {
|
if (free_mode_ == FREE_DATA) {
|
||||||
free(data_);
|
env()->isolate()->GetArrayBufferAllocator()->Free(data_, free_size);
|
||||||
data_ = nullptr;
|
data_ = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4840,7 +4859,8 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
|
||||||
Local<Object> obj = env->randombytes_constructor_template()->
|
Local<Object> obj = env->randombytes_constructor_template()->
|
||||||
NewInstance(env->context()).ToLocalChecked();
|
NewInstance(env->context()).ToLocalChecked();
|
||||||
char* data = node::Malloc(size);
|
char* data = static_cast<char*>(
|
||||||
|
env->isolate()->GetArrayBufferAllocator()->AllocateUninitialized(size));
|
||||||
std::unique_ptr<RandomBytesRequest> req(
|
std::unique_ptr<RandomBytesRequest> req(
|
||||||
new RandomBytesRequest(env,
|
new RandomBytesRequest(env,
|
||||||
obj,
|
obj,
|
||||||
|
@ -5015,8 +5035,9 @@ 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;
|
char* buf = nullptr;
|
||||||
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
|
|
||||||
BIOPointer bio(BIO_new(BIO_s_mem()));
|
BIOPointer bio(BIO_new(BIO_s_mem()));
|
||||||
if (!bio)
|
if (!bio)
|
||||||
|
@ -5037,7 +5058,7 @@ char* ExportPublicKey(const char* data, int len, size_t* size) {
|
||||||
BIO_get_mem_ptr(bio.get(), &ptr);
|
BIO_get_mem_ptr(bio.get(), &ptr);
|
||||||
|
|
||||||
*size = ptr->length;
|
*size = ptr->length;
|
||||||
buf = Malloc(*size);
|
buf = static_cast<char*>(allocator->AllocateUninitialized(*size));
|
||||||
memcpy(buf, ptr->data, *size);
|
memcpy(buf, ptr->data, *size);
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
|
@ -5055,7 +5076,7 @@ void ExportPublicKey(const FunctionCallbackInfo<Value>& args) {
|
||||||
CHECK_NE(data, nullptr);
|
CHECK_NE(data, nullptr);
|
||||||
|
|
||||||
size_t pkey_size;
|
size_t pkey_size;
|
||||||
char* pkey = ExportPublicKey(data, length, &pkey_size);
|
char* pkey = ExportPublicKey(env, data, length, &pkey_size);
|
||||||
if (pkey == nullptr)
|
if (pkey == nullptr)
|
||||||
return args.GetReturnValue().SetEmptyString();
|
return args.GetReturnValue().SetEmptyString();
|
||||||
|
|
||||||
|
|
|
@ -554,7 +554,8 @@ class PublicKeyCipher {
|
||||||
template <Operation operation,
|
template <Operation operation,
|
||||||
EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
|
EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
|
||||||
EVP_PKEY_cipher_t EVP_PKEY_cipher>
|
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,
|
int key_pem_len,
|
||||||
const char* passphrase,
|
const char* passphrase,
|
||||||
int padding,
|
int padding,
|
||||||
|
|
|
@ -355,7 +355,13 @@ void StreamResource::ClearError() {
|
||||||
|
|
||||||
|
|
||||||
uv_buf_t StreamListener::OnStreamAlloc(size_t suggested_size) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -363,11 +369,12 @@ void EmitToJSStreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf) {
|
||||||
CHECK_NE(stream_, nullptr);
|
CHECK_NE(stream_, nullptr);
|
||||||
StreamBase* stream = static_cast<StreamBase*>(stream_);
|
StreamBase* stream = static_cast<StreamBase*>(stream_);
|
||||||
Environment* env = stream->stream_env();
|
Environment* env = stream->stream_env();
|
||||||
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
HandleScope handle_scope(env->isolate());
|
HandleScope handle_scope(env->isolate());
|
||||||
Context::Scope context_scope(env->context());
|
Context::Scope context_scope(env->context());
|
||||||
|
|
||||||
if (nread <= 0) {
|
if (nread <= 0) {
|
||||||
free(buf.base);
|
allocator->Free(buf.base, buf.len);
|
||||||
if (nread < 0)
|
if (nread < 0)
|
||||||
stream->CallJSOnreadMethod(nread, Local<Object>());
|
stream->CallJSOnreadMethod(nread, Local<Object>());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -447,7 +447,10 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
|
||||||
void UDPWrap::OnAlloc(uv_handle_t* handle,
|
void UDPWrap::OnAlloc(uv_handle_t* handle,
|
||||||
size_t suggested_size,
|
size_t suggested_size,
|
||||||
uv_buf_t* buf) {
|
uv_buf_t* buf) {
|
||||||
buf->base = node::Malloc(suggested_size);
|
auto* wrap = static_cast<UDPWrap*>(handle->data);
|
||||||
|
auto* allocator = wrap->env()->isolate()->GetArrayBufferAllocator();
|
||||||
|
buf->base =
|
||||||
|
static_cast<char*>(allocator->AllocateUninitialized(suggested_size));
|
||||||
buf->len = suggested_size;
|
buf->len = suggested_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,14 +460,15 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
|
||||||
const uv_buf_t* buf,
|
const uv_buf_t* buf,
|
||||||
const struct sockaddr* addr,
|
const struct sockaddr* addr,
|
||||||
unsigned int flags) {
|
unsigned int flags) {
|
||||||
if (nread == 0 && addr == nullptr) {
|
|
||||||
if (buf->base != nullptr)
|
|
||||||
free(buf->base);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UDPWrap* wrap = static_cast<UDPWrap*>(handle->data);
|
UDPWrap* wrap = static_cast<UDPWrap*>(handle->data);
|
||||||
Environment* env = wrap->env();
|
Environment* env = wrap->env();
|
||||||
|
auto* allocator = env->isolate()->GetArrayBufferAllocator();
|
||||||
|
|
||||||
|
if (nread == 0 && addr == nullptr) {
|
||||||
|
if (buf->base != nullptr)
|
||||||
|
allocator->Free(buf->base, buf->len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
HandleScope handle_scope(env->isolate());
|
HandleScope handle_scope(env->isolate());
|
||||||
Context::Scope context_scope(env->context());
|
Context::Scope context_scope(env->context());
|
||||||
|
@ -479,13 +483,15 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
|
||||||
|
|
||||||
if (nread < 0) {
|
if (nread < 0) {
|
||||||
if (buf->base != nullptr)
|
if (buf->base != nullptr)
|
||||||
free(buf->base);
|
allocator->Free(buf->base, buf->len);
|
||||||
wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv);
|
wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* base = node::UncheckedRealloc(buf->base, nread);
|
// Note that nread may be smaller thant buf->len, in that case the length
|
||||||
argv[2] = Buffer::New(env, base, nread).ToLocalChecked();
|
// 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);
|
argv[3] = AddressToJS(env, addr);
|
||||||
wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv);
|
wrap->MakeCallback(env->onmessage_string(), arraysize(argv), argv);
|
||||||
}
|
}
|
||||||
|
|
19
src/util.h
19
src/util.h
|
@ -424,24 +424,35 @@ template <typename T>
|
||||||
struct MallocedBuffer {
|
struct MallocedBuffer {
|
||||||
T* data;
|
T* data;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
v8::ArrayBuffer::Allocator* allocator;
|
||||||
|
|
||||||
T* release() {
|
T* release() {
|
||||||
|
allocator = nullptr;
|
||||||
T* ret = data;
|
T* ret = data;
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
MallocedBuffer() : data(nullptr) {}
|
MallocedBuffer() : data(nullptr), allocator(nullptr) {}
|
||||||
explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}
|
MallocedBuffer(size_t size, v8::ArrayBuffer::Allocator* allocator)
|
||||||
MallocedBuffer(MallocedBuffer&& other) : data(other.data), size(other.size) {
|
: size(size), allocator(allocator) {
|
||||||
|
data = static_cast<T*>(allocator->AllocateUninitialized(size));
|
||||||
|
}
|
||||||
|
MallocedBuffer(MallocedBuffer&& other)
|
||||||
|
: data(other.data), size(other.size), allocator(other.allocator) {
|
||||||
other.data = nullptr;
|
other.data = nullptr;
|
||||||
|
other.allocator = nullptr;
|
||||||
}
|
}
|
||||||
MallocedBuffer& operator=(MallocedBuffer&& other) {
|
MallocedBuffer& operator=(MallocedBuffer&& other) {
|
||||||
this->~MallocedBuffer();
|
this->~MallocedBuffer();
|
||||||
return *new(this) MallocedBuffer(other);
|
return *new(this) MallocedBuffer(other);
|
||||||
}
|
}
|
||||||
~MallocedBuffer() {
|
~MallocedBuffer() {
|
||||||
free(data);
|
if (allocator) {
|
||||||
|
allocator->Free(data, size);
|
||||||
|
} else {
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MallocedBuffer(const MallocedBuffer&) = delete;
|
MallocedBuffer(const MallocedBuffer&) = delete;
|
||||||
MallocedBuffer& operator=(const MallocedBuffer&) = delete;
|
MallocedBuffer& operator=(const MallocedBuffer&) = delete;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче