pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/nodejs/node/commit/c69c6f14f2b486b66293f01e0bc47ef95cbe52c0

el="stylesheet" href="https://github.githubassets.com/assets/global-d18f184ea1a06a2c.css" /> src: simplify and fix FFI ArrayBuffer accesses · nodejs/node@c69c6f1 · GitHub
Skip to content

Commit c69c6f1

Browse files
authored
src: simplify and fix FFI ArrayBuffer accesses
`ArrayBufferViewContents` supports `ArrayBuffer`s, so we do not need to provide special treatment for those. Also, small typed arrays may not have backing stores until their corresponding `ArrayBuffer`s are accessed, so do that in order to avoid accidentally accessing arbitrary stack memory. Signed-off-by: Anna Henningsen <anna@addaleax.net> PR-URL: #62857 Reviewed-By: Paolo Insogna <paolo@cowtech.it> Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
1 parent 5be0bd9 commit c69c6f1

1 file changed

Lines changed: 32 additions & 36 deletions

File tree

src/ffi/data.cc

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ using v8::MaybeLocal;
2525
using v8::NewStringType;
2626
using v8::Number;
2727
using v8::Object;
28+
using v8::SharedArrayBuffer;
2829
using v8::String;
2930
using v8::Value;
3031

@@ -675,26 +676,17 @@ void ExportBytes(const FunctionCallbackInfo<Value>& args) {
675676
return;
676677
}
677678

678-
const uint8_t* source_data = nullptr;
679-
size_t source_len = 0;
679+
// This needs to be kept alive until the data
680+
// is actually copied.
681+
ArrayBufferViewContents<uint8_t> view;
680682

681-
if (args[0]->IsArrayBuffer()) {
682-
Local<ArrayBuffer> array_buffer = args[0].As<ArrayBuffer>();
683-
std::shared_ptr<BackingStore> store = array_buffer->GetBackingStore();
684-
if (!store) {
685-
THROW_ERR_INVALID_ARG_VALUE(env, "Invalid ArrayBuffer backing store");
686-
return;
687-
}
688-
source_data = static_cast<const uint8_t*>(store->Data());
689-
source_len = array_buffer->ByteLength();
690-
} else if (args[0]->IsArrayBufferView()) {
691-
ArrayBufferViewContents<uint8_t> view(args[0]);
683+
if (args[0]->IsArrayBuffer() || args[0]->IsSharedArrayBuffer() ||
684+
args[0]->IsArrayBufferView()) {
685+
view.ReadValue(args[0]);
692686
if (view.WasDetached()) {
693687
THROW_ERR_INVALID_ARG_VALUE(env, "Invalid ArrayBufferView backing store");
694688
return;
695689
}
696-
source_data = view.data();
697-
source_len = view.length();
698690
} else {
699691
THROW_ERR_INVALID_ARG_TYPE(
700692
env,
@@ -713,12 +705,12 @@ void ExportBytes(const FunctionCallbackInfo<Value>& args) {
713705
return;
714706
}
715707

716-
if (len < source_len) {
708+
if (len < view.length()) {
717709
THROW_ERR_OUT_OF_RANGE(env, "The length must be >= source byte length");
718710
return;
719711
}
720712

721-
if (ptr == 0 && source_len > 0) {
713+
if (ptr == 0 && view.length() > 0) {
722714
THROW_ERR_FFI_INVALID_POINTER(env,
723715
"Cannot create a buffer from a null pointer");
724716
return;
@@ -733,9 +725,7 @@ void ExportBytes(const FunctionCallbackInfo<Value>& args) {
733725
return;
734726
}
735727

736-
if (source_len > 0) {
737-
std::memcpy(reinterpret_cast<void*>(ptr), source_data, source_len);
738-
}
728+
std::memcpy(reinterpret_cast<void*>(ptr), view.data(), view.length());
739729
}
740730

741731
void GetRawPointer(const FunctionCallbackInfo<Value>& args) {
@@ -752,28 +742,34 @@ void GetRawPointer(const FunctionCallbackInfo<Value>& args) {
752742
}
753743

754744
uintptr_t ptr = 0;
745+
size_t offset = 0;
746+
std::shared_ptr<BackingStore> store;
755747

756748
if (args[0]->IsArrayBuffer()) {
757-
Local<ArrayBuffer> array_buffer = args[0].As<ArrayBuffer>();
758-
std::shared_ptr<BackingStore> store = array_buffer->GetBackingStore();
759-
if (!store) {
760-
THROW_ERR_INVALID_ARG_VALUE(env, "Invalid ArrayBuffer backing store");
761-
return;
762-
}
763-
ptr = reinterpret_cast<uintptr_t>(store->Data());
749+
store = args[0].As<ArrayBuffer>()->GetBackingStore();
750+
} else if (args[0]->IsSharedArrayBuffer()) {
751+
store = args[0].As<SharedArrayBuffer>()->GetBackingStore();
764752
} else if (args[0]->IsArrayBufferView()) {
765-
ArrayBufferViewContents<uint8_t> view(args[0]);
766-
if (view.WasDetached()) {
767-
THROW_ERR_INVALID_ARG_VALUE(env, "Invalid ArrayBufferView backing store");
768-
return;
769-
}
770-
ptr = reinterpret_cast<uintptr_t>(view.data());
753+
// Access the store here to ensure that it exists. Small typed arrays
754+
// may not have a store until this point and can instead be stored
755+
// entirely in-heap.
756+
store = args[0].As<ArrayBufferView>()->Buffer()->GetBackingStore();
757+
offset = args[0].As<ArrayBufferView>()->ByteOffset();
771758
} else {
772-
THROW_ERR_INVALID_ARG_TYPE(
773-
env,
774-
"The first argument must be a Buffer, ArrayBuffer, or ArrayBufferView");
759+
THROW_ERR_INVALID_ARG_TYPE(env,
760+
"The first argument must be a Buffer, "
761+
"ArrayBuffer, or ArrayBufferView");
762+
return;
763+
}
764+
765+
// WARNING: There is no inherent guarantee that the pointer returned
766+
// from this function will be valid beyond the lifetime of the BackingStore
767+
// instance!
768+
if (!store) {
769+
THROW_ERR_INVALID_ARG_VALUE(env, "Invalid ArrayBuffer backing store");
775770
return;
776771
}
772+
ptr = reinterpret_cast<uintptr_t>(store->Data()) + offset;
777773

778774
args.GetReturnValue().Set(
779775
BigInt::NewFromUnsigned(isolate, static_cast<uint64_t>(ptr)));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy