Skip to content

Commit

Permalink
src: stop using v8::BackingStore::Reallocate
Browse files Browse the repository at this point in the history
It's being deprecated by V8.
Explicitly allocate a new ArrayBuffer and copy the data when needed
instead.

Fixes: #52234
Co-authored-by: Joyee Cheung <[email protected]>
  • Loading branch information
targos and joyeecheung committed Mar 31, 2024
1 parent 9efc84a commit d5adde1
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 20 deletions.
33 changes: 23 additions & 10 deletions src/crypto/crypto_cipher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -820,10 +820,15 @@ CipherBase::UpdateResult CipherBase::Update(
len);

CHECK_LE(static_cast<size_t>(buf_len), (*out)->ByteLength());
if (buf_len == 0)
if (buf_len == 0) {
*out = ArrayBuffer::NewBackingStore(env()->isolate(), 0);
else
*out = BackingStore::Reallocate(env()->isolate(), std::move(*out), buf_len);
} else if (static_cast<size_t>(buf_len) != (*out)->ByteLength()) {
std::unique_ptr<BackingStore> old_out = std::move(*out);
*out = ArrayBuffer::NewBackingStore(env()->isolate(), buf_len);
memcpy(static_cast<char*>((*out)->Data()),
static_cast<char*>(old_out->Data()),
buf_len);
}

// When in CCM mode, EVP_CipherUpdate will fail if the authentication tag is
// invalid. In that case, remember the error and throw in final().
Expand Down Expand Up @@ -911,11 +916,14 @@ bool CipherBase::Final(std::unique_ptr<BackingStore>* out) {
&out_len) == 1;

CHECK_LE(static_cast<size_t>(out_len), (*out)->ByteLength());
if (out_len > 0) {
*out =
BackingStore::Reallocate(env()->isolate(), std::move(*out), out_len);
} else {
if (out_len == 0) {
*out = ArrayBuffer::NewBackingStore(env()->isolate(), 0);
} else if (static_cast<size_t>(out_len) != (*out)->ByteLength()) {
std::unique_ptr<BackingStore> old_out = std::move(*out);
*out = ArrayBuffer::NewBackingStore(env()->isolate(), out_len);
memcpy(static_cast<char*>((*out)->Data()),
static_cast<char*>(old_out->Data()),
out_len);
}

if (ok && kind_ == kCipher && IsAuthenticatedMode()) {
Expand Down Expand Up @@ -1015,10 +1023,15 @@ bool PublicKeyCipher::Cipher(
}

CHECK_LE(out_len, (*out)->ByteLength());
if (out_len > 0)
*out = BackingStore::Reallocate(env->isolate(), std::move(*out), out_len);
else
if (out_len == 0) {
*out = ArrayBuffer::NewBackingStore(env->isolate(), 0);
} else if (out_len != (*out)->ByteLength()) {
std::unique_ptr<BackingStore> old_out = std::move(*out);
*out = ArrayBuffer::NewBackingStore(env->isolate(), out_len);
memcpy(static_cast<char*>((*out)->Data()),
static_cast<char*>(old_out->Data()),
out_len);
}

return true;
}
Expand Down
11 changes: 8 additions & 3 deletions src/crypto/crypto_sig.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,15 @@ std::unique_ptr<BackingStore> Node_SignFinal(Environment* env,
EVP_PKEY_sign(pkctx.get(), static_cast<unsigned char*>(sig->Data()),
&sig_len, m, m_len)) {
CHECK_LE(sig_len, sig->ByteLength());
if (sig_len == 0)
if (sig_len == 0) {
sig = ArrayBuffer::NewBackingStore(env->isolate(), 0);
else
sig = BackingStore::Reallocate(env->isolate(), std::move(sig), sig_len);
} else if (sig_len != sig->ByteLength()) {
std::unique_ptr<BackingStore> old_sig = std::move(sig);
sig = ArrayBuffer::NewBackingStore(env->isolate(), sig_len);
memcpy(static_cast<char*>(sig->Data()),
static_cast<char*>(old_sig->Data()),
sig_len);
}
return sig;
}

Expand Down
9 changes: 7 additions & 2 deletions src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,13 @@ MaybeLocal<Object> New(Isolate* isolate,
CHECK(actual <= length);

if (LIKELY(actual > 0)) {
if (actual < length)
store = BackingStore::Reallocate(isolate, std::move(store), actual);
if (actual < length) {
std::unique_ptr<BackingStore> old_store = std::move(store);
store = ArrayBuffer::NewBackingStore(isolate, actual);
memcpy(static_cast<char*>(store->Data()),
static_cast<char*>(old_store->Data()),
actual);
}
Local<ArrayBuffer> buf = ArrayBuffer::New(isolate, std::move(store));
Local<Object> obj;
if (UNLIKELY(!New(isolate, buf, 0, actual).ToLocal(&obj)))
Expand Down
9 changes: 7 additions & 2 deletions src/node_http2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2023,9 +2023,14 @@ void Http2Session::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) {

statistics_.data_received += nread;

if (LIKELY(stream_buf_offset_ == 0)) {
if (LIKELY(stream_buf_offset_ == 0 &&
static_cast<size_t>(nread) != bs->ByteLength())) {
// Shrink to the actual amount of used data.
bs = BackingStore::Reallocate(env()->isolate(), std::move(bs), nread);
std::unique_ptr<BackingStore> old_bs = std::move(bs);
bs = ArrayBuffer::NewBackingStore(env()->isolate(), nread);
memcpy(static_cast<char*>(bs->Data()),
static_cast<char*>(old_bs->Data()),
nread);
} else {
// This is a very unlikely case, and should only happen if the ReadStart()
// call in OnStreamAfterWrite() immediately provides data. If that does
Expand Down
8 changes: 7 additions & 1 deletion src/stream_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,13 @@ void EmitToJSStreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) {
}

CHECK_LE(static_cast<size_t>(nread), bs->ByteLength());
bs = BackingStore::Reallocate(isolate, std::move(bs), nread);
if (static_cast<size_t>(nread) != bs->ByteLength()) {
std::unique_ptr<BackingStore> old_bs = std::move(bs);
bs = ArrayBuffer::NewBackingStore(isolate, nread);
memcpy(static_cast<char*>(bs->Data()),
static_cast<char*>(old_bs->Data()),
nread);
}

stream->CallJSOnreadMethod(nread, ArrayBuffer::New(isolate, std::move(bs)));
}
Expand Down
8 changes: 6 additions & 2 deletions src/udp_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -764,9 +764,13 @@ void UDPWrap::OnRecv(ssize_t nread,
return;
} else if (nread == 0) {
bs = ArrayBuffer::NewBackingStore(isolate, 0);
} else {
} else if (static_cast<size_t>(nread) != bs->ByteLength()) {
CHECK_LE(static_cast<size_t>(nread), bs->ByteLength());
bs = BackingStore::Reallocate(isolate, std::move(bs), nread);
std::unique_ptr<BackingStore> old_bs = std::move(bs);
bs = ArrayBuffer::NewBackingStore(isolate, nread);
memcpy(static_cast<char*>(bs->Data()),
static_cast<char*>(old_bs->Data()),
nread);
}

Local<Object> address;
Expand Down

0 comments on commit d5adde1

Please sign in to comment.