From ec1550407bbb6da90cea50f3c1ea2ad96ec03392 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Fri, 5 Apr 2024 11:20:10 +0200 Subject: [PATCH] src: stop using `v8::BackingStore::Reallocate` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's being deprecated by V8. Explicitly allocate a new ArrayBuffer and copy the data when needed instead. Fixes: https://github.com/nodejs/node/issues/52234 Co-authored-by: Joyee Cheung PR-URL: https://github.com/nodejs/node/pull/52292 Reviewed-By: Anna Henningsen Reviewed-By: Tobias Nießen --- src/crypto/crypto_cipher.cc | 33 +++++++++++++++++++++++---------- src/crypto/crypto_sig.cc | 11 ++++++++--- src/node_buffer.cc | 9 +++++++-- src/node_http2.cc | 9 +++++++-- src/stream_base.cc | 8 +++++++- src/udp_wrap.cc | 8 ++++++-- 6 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/crypto/crypto_cipher.cc b/src/crypto/crypto_cipher.cc index 8cc2b1786c98b9..4b5cdca9719da5 100644 --- a/src/crypto/crypto_cipher.cc +++ b/src/crypto/crypto_cipher.cc @@ -820,10 +820,15 @@ CipherBase::UpdateResult CipherBase::Update( len); CHECK_LE(static_cast(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(buf_len) != (*out)->ByteLength()) { + std::unique_ptr old_out = std::move(*out); + *out = ArrayBuffer::NewBackingStore(env()->isolate(), buf_len); + memcpy(static_cast((*out)->Data()), + static_cast(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(). @@ -911,11 +916,14 @@ bool CipherBase::Final(std::unique_ptr* out) { &out_len) == 1; CHECK_LE(static_cast(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(out_len) != (*out)->ByteLength()) { + std::unique_ptr old_out = std::move(*out); + *out = ArrayBuffer::NewBackingStore(env()->isolate(), out_len); + memcpy(static_cast((*out)->Data()), + static_cast(old_out->Data()), + out_len); } if (ok && kind_ == kCipher && IsAuthenticatedMode()) { @@ -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 old_out = std::move(*out); + *out = ArrayBuffer::NewBackingStore(env->isolate(), out_len); + memcpy(static_cast((*out)->Data()), + static_cast(old_out->Data()), + out_len); + } return true; } diff --git a/src/crypto/crypto_sig.cc b/src/crypto/crypto_sig.cc index 5b1acf2677d1b6..3b4fdee18a7e6d 100644 --- a/src/crypto/crypto_sig.cc +++ b/src/crypto/crypto_sig.cc @@ -99,10 +99,15 @@ std::unique_ptr Node_SignFinal(Environment* env, EVP_PKEY_sign(pkctx.get(), static_cast(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 old_sig = std::move(sig); + sig = ArrayBuffer::NewBackingStore(env->isolate(), sig_len); + memcpy(static_cast(sig->Data()), + static_cast(old_sig->Data()), + sig_len); + } return sig; } diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 300060f9d24290..82e98193ba0fdf 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -324,8 +324,13 @@ MaybeLocal 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 old_store = std::move(store); + store = ArrayBuffer::NewBackingStore(isolate, actual); + memcpy(static_cast(store->Data()), + static_cast(old_store->Data()), + actual); + } Local buf = ArrayBuffer::New(isolate, std::move(store)); Local obj; if (UNLIKELY(!New(isolate, buf, 0, actual).ToLocal(&obj))) diff --git a/src/node_http2.cc b/src/node_http2.cc index cf99e21928d89b..eada40816d4689 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -2029,9 +2029,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(nread) != bs->ByteLength())) { // Shrink to the actual amount of used data. - bs = BackingStore::Reallocate(env()->isolate(), std::move(bs), nread); + std::unique_ptr old_bs = std::move(bs); + bs = ArrayBuffer::NewBackingStore(env()->isolate(), nread); + memcpy(static_cast(bs->Data()), + static_cast(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 diff --git a/src/stream_base.cc b/src/stream_base.cc index 74001d5b6cee00..af714734f49b83 100644 --- a/src/stream_base.cc +++ b/src/stream_base.cc @@ -679,7 +679,13 @@ void EmitToJSStreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) { } CHECK_LE(static_cast(nread), bs->ByteLength()); - bs = BackingStore::Reallocate(isolate, std::move(bs), nread); + if (static_cast(nread) != bs->ByteLength()) { + std::unique_ptr old_bs = std::move(bs); + bs = ArrayBuffer::NewBackingStore(isolate, nread); + memcpy(static_cast(bs->Data()), + static_cast(old_bs->Data()), + nread); + } stream->CallJSOnreadMethod(nread, ArrayBuffer::New(isolate, std::move(bs))); } diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index d4249d7aac56e0..a7c6bc6ae07607 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -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(nread) != bs->ByteLength()) { CHECK_LE(static_cast(nread), bs->ByteLength()); - bs = BackingStore::Reallocate(isolate, std::move(bs), nread); + std::unique_ptr old_bs = std::move(bs); + bs = ArrayBuffer::NewBackingStore(isolate, nread); + memcpy(static_cast(bs->Data()), + static_cast(old_bs->Data()), + nread); } Local address;