@@ -6,63 +6,6 @@ Subject: support V8 sandboxed pointers
66This refactors several allocators to allocate within the V8 memory cage,
77allowing them to be compatible with the V8_SANDBOXED_POINTERS feature.
88
9- diff --git a/src/api/environment.cc b/src/api/environment.cc
10- index fd71ceac65ccef1d2832b45b0b5612877cee22c1..cb37fa080fc8e8d524cfa2758c4a8c2c5652324d 100644
11- --- a/src/api/environment.cc
12- +++ b/src/api/environment.cc
13- @@ -106,6 +106,14 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
14- return result;
15- }
16-
17- + NodeArrayBufferAllocator::NodeArrayBufferAllocator() {
18- + zero_fill_field_ = static_cast<uint32_t*>(allocator_->Allocate(sizeof(*zero_fill_field_)));
19- + }
20- +
21- + NodeArrayBufferAllocator::~NodeArrayBufferAllocator() {
22- + allocator_->Free(zero_fill_field_, sizeof(*zero_fill_field_));
23- + }
24- +
25- void* NodeArrayBufferAllocator::Allocate(size_t size) {
26- void* ret;
27- if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers)
28- diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc
29- index f23cedf4f2449d8edc9a8de1b70332e75d693cdd..976653dd1e9363e046788fc3419a9b649ceb2ea4 100644
30- --- a/src/crypto/crypto_dh.cc
31- +++ b/src/crypto/crypto_dh.cc
32- @@ -55,13 +55,32 @@ void DiffieHellman::MemoryInfo(MemoryTracker* tracker) const {
33-
34- namespace {
35- MaybeLocal<Value> DataPointerToBuffer(Environment* env, DataPointer&& data) {
36- + #if defined(V8_ENABLE_SANDBOX)
37- + std::unique_ptr<v8::BackingStore> backing;
38- + if (data.size() > 0) {
39- + std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
40- + void* v8_data = allocator->Allocate(data.size());
41- + CHECK(v8_data);
42- + memcpy(v8_data, data.get(), data.size());
43- + backing = ArrayBuffer::NewBackingStore(
44- + v8_data,
45- + data.size(),
46- + [](void* data, size_t length, void*) {
47- + std::unique_ptr<ArrayBuffer::Allocator> allocator(ArrayBuffer::Allocator::NewDefaultAllocator());
48- + allocator->Free(data, length);
49- + }, nullptr);
50- + } else {
51- + NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
52- + backing = v8::ArrayBuffer::NewBackingStore(env->isolate(), data.size());
53- + }
54- + #else
55- auto backing = ArrayBuffer::NewBackingStore(
56- data.get(),
57- data.size(),
58- [](void* data, size_t len, void* ptr) { DataPointer free_me(data, len); },
59- nullptr);
60- data.release();
61- -
62- + #endif
63- auto ab = ArrayBuffer::New(env->isolate(), std::move(backing));
64- return Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local<Value>());
65- }
669diff --git a/src/crypto/crypto_util.cc b/src/crypto/crypto_util.cc
6710index 4505786745c54a529f904d5e7813a86204e0a78b..eab18ab9888e2f7c0757fefab80505d8c99dc742 100644
6811--- a/src/crypto/crypto_util.cc
@@ -189,64 +132,10 @@ index f616223cfb0f6e10f7cf57ada9704316bde2797e..eb6dad44a49d997097c8fb5009eeb60a
189132 Local<Value> ret;
190133 if (!Buffer::New(env, ab, 0, ab->ByteLength()).ToLocal(&ret)) return {};
191134diff --git a/src/node_buffer.cc b/src/node_buffer.cc
192- index 357dc5f6d1c1c2d3756a94c1326b0502403e1eaf..45c6b4cf19f7b336891dae3cd84d698507227d9e 100644
135+ index 357dc5f6d1c1c2d3756a94c1326b0502403e1eaf..b9f0c97938203b4652780a7d707c5e83319330b0 100644
193136--- a/src/node_buffer.cc
194137+++ b/src/node_buffer.cc
195- @@ -78,6 +78,7 @@ using v8::SharedArrayBuffer;
196- using v8::String;
197- using v8::Uint32;
198- using v8::Uint8Array;
199- + using v8::Uint32Array;
200- using v8::Value;
201-
202- namespace {
203- @@ -1228,6 +1229,45 @@ void SetBufferPrototype(const FunctionCallbackInfo<Value>& args) {
204- realm->set_buffer_prototype_object(proto);
205- }
206-
207- + void GetZeroFillToggle(const FunctionCallbackInfo<Value>& args) {
208- + Environment* env = Environment::GetCurrent(args);
209- + NodeArrayBufferAllocator* allocator = env->isolate_data()->node_allocator();
210- + Local<ArrayBuffer> ab;
211- + // It can be a nullptr when running inside an isolate where we
212- + // do not own the ArrayBuffer allocator.
213- + if (allocator == nullptr || env->isolate_data()->is_building_snapshot()) {
214- + // Create a dummy Uint32Array - the JS land can only toggle the C++ land
215- + // setting when the allocator uses our toggle. With this the toggle in JS
216- + // land results in no-ops.
217- + // When building a snapshot, just use a dummy toggle as well to avoid
218- + // introducing the dynamic external reference. We'll re-initialize the
219- + // toggle with a real one connected to the C++ allocator after snapshot
220- + // deserialization.
221- +
222- + ab = ArrayBuffer::New(env->isolate(), sizeof(uint32_t));
223- + } else {
224- + // TODO(joyeecheung): save ab->GetBackingStore()->Data() in the Node.js
225- + // array buffer allocator and include it into the C++ toggle while the
226- + // Environment is still alive.
227- + uint32_t* zero_fill_field = allocator->zero_fill_field();
228- + std::unique_ptr<BackingStore> backing =
229- + ArrayBuffer::NewBackingStore(zero_fill_field,
230- + sizeof(*zero_fill_field),
231- + [](void*, size_t, void*) {},
232- + nullptr);
233- + ab = ArrayBuffer::New(env->isolate(), std::move(backing));
234- + }
235- +
236- + if (ab->SetPrivate(env->context(),
237- + env->untransferable_object_private_symbol(),
238- + True(env->isolate()))
239- + .IsNothing()) {
240- + return;
241- + }
242- +
243- + args.GetReturnValue().Set(Uint32Array::New(ab, 0, 1));
244- + }
245- +
246- static void Btoa(const FunctionCallbackInfo<Value>& args) {
247- CHECK_EQ(args.Length(), 1);
248- Environment* env = Environment::GetCurrent(args);
249- @@ -1412,7 +1452,7 @@ inline size_t CheckNumberToSize(Local<Value> number) {
138+ @@ -1412,7 +1412,7 @@ inline size_t CheckNumberToSize(Local<Value> number) {
250139 CHECK(value >= 0 && value < maxSize);
251140 size_t size = static_cast<size_t>(value);
252141 #ifdef V8_ENABLE_SANDBOX
@@ -255,7 +144,7 @@ index 357dc5f6d1c1c2d3756a94c1326b0502403e1eaf..45c6b4cf19f7b336891dae3cd84d6985
255144 #endif
256145 return size;
257146 }
258- @@ -1437,7 +1477 ,7 @@ void CreateUnsafeArrayBuffer(const FunctionCallbackInfo<Value>& args) {
147+ @@ -1437,7 +1437 ,7 @@ void CreateUnsafeArrayBuffer(const FunctionCallbackInfo<Value>& args) {
259148 buf = ArrayBuffer::New(isolate, size);
260149 } else {
261150 std::unique_ptr<BackingStore> store =
@@ -264,22 +153,6 @@ index 357dc5f6d1c1c2d3756a94c1326b0502403e1eaf..45c6b4cf19f7b336891dae3cd84d6985
264153 if (!store) {
265154 return env->ThrowRangeError("Array buffer allocation failed");
266155 }
267- @@ -1615,6 +1655,7 @@ void Initialize(Local<Object> target,
268- "utf8WriteStatic",
269- SlowWriteString<UTF8>,
270- &fast_write_string_utf8);
271- + SetMethod(context, target, "getZeroFillToggle", GetZeroFillToggle);
272- }
273-
274- } // anonymous namespace
275- @@ -1663,6 +1704,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
276- registry->Register(StringWrite<HEX>);
277- registry->Register(StringWrite<UCS2>);
278- registry->Register(StringWrite<UTF8>);
279- + registry->Register(GetZeroFillToggle);
280-
281- registry->Register(CopyArrayBuffer);
282- registry->Register(CreateUnsafeArrayBuffer);
283156diff --git a/src/node_i18n.cc b/src/node_i18n.cc
284157index 6be3920632b25db450025ebab6a2636e4811cdbe..b49916d2b5fc5e58cf3fb67329430fd3df8fb813 100644
285158--- a/src/node_i18n.cc
@@ -320,30 +193,6 @@ index 6be3920632b25db450025ebab6a2636e4811cdbe..b49916d2b5fc5e58cf3fb67329430fd3
320193 }
321194
322195 constexpr const char* EncodingName(const enum encoding encoding) {
323- diff --git a/src/node_internals.h b/src/node_internals.h
324- index 12ea72b61b0a5e194207bb369dfed4b8667107cb..64442215714a98f648971e517ddd9c77e38fe3f2 100644
325- --- a/src/node_internals.h
326- +++ b/src/node_internals.h
327- @@ -121,7 +121,9 @@ v8::MaybeLocal<v8::Object> InitializePrivateSymbols(
328-
329- class NodeArrayBufferAllocator : public ArrayBufferAllocator {
330- public:
331- - inline uint32_t* zero_fill_field() { return &zero_fill_field_; }
332- + NodeArrayBufferAllocator();
333- + ~NodeArrayBufferAllocator() override;
334- + inline uint32_t* zero_fill_field() { return zero_fill_field_; }
335-
336- void* Allocate(size_t size) override; // Defined in src/node.cc
337- void* AllocateUninitialized(size_t size) override;
338- @@ -139,7 +141,7 @@ class NodeArrayBufferAllocator : public ArrayBufferAllocator {
339- }
340-
341- private:
342- - uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land.
343- + uint32_t* zero_fill_field_ = nullptr; // Boolean but exposed as uint32 to JS land.
344- std::atomic<size_t> total_mem_usage_ {0};
345-
346- // Delegate to V8's allocator for compatibility with the V8 memory cage.
347196diff --git a/src/node_serdes.cc b/src/node_serdes.cc
348197index c55a2e28066147ae5ca5def10ec76ccc03c634b4..c54183c72944989219b6437c9e571a3f7f3f8dd5 100644
349198--- a/src/node_serdes.cc
0 commit comments