@@ -34,6 +34,8 @@ using ncrypto::EnginePointer;
3434using ncrypto::SSLPointer;
3535using v8::ArrayBuffer;
3636using v8::BackingStore;
37+ using v8::BackingStoreInitializationMode;
38+ using v8::BackingStoreOnFailureMode;
3739using v8::BigInt;
3840using v8::Context;
3941using v8::EscapableHandleScope;
@@ -339,16 +341,37 @@ ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
339341 return *this ;
340342}
341343
342- std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore () {
344+ std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore (
345+ Environment* env) {
343346 // It's ok for allocated_data_ to be nullptr but
344347 // only if size_ is zero.
345348 CHECK_IMPLIES (size_ > 0 , allocated_data_ != nullptr );
349+ #ifdef V8_ENABLE_SANDBOX
350+ // If the v8 sandbox is enabled, then all array buffers must be allocated
351+ // via the isolate. External buffers are not allowed. So, instead of wrapping
352+ // the allocated data we'll copy it instead.
353+
354+ // TODO(@jasnell): It would be nice to use an abstracted utility to do this
355+ // branch instead of duplicating the V8_ENABLE_SANDBOX check each time.
356+ std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore (
357+ env->isolate (),
358+ size (),
359+ BackingStoreInitializationMode::kUninitialized ,
360+ BackingStoreOnFailureMode::kReturnNull );
361+ if (!ptr) {
362+ THROW_ERR_MEMORY_ALLOCATION_FAILED (env);
363+ return nullptr ;
364+ }
365+ memcpy (ptr->Data (), allocated_data_, size ());
366+ OPENSSL_clear_free (allocated_data_, size_);
367+ #else
346368 std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore (
347369 allocated_data_,
348370 size (),
349371 [](void * data, size_t length, void * deleter_data) {
350372 OPENSSL_clear_free (deleter_data, length);
351373 }, allocated_data_);
374+ #endif // V8_ENABLE_SANDBOX
352375 CHECK (ptr);
353376 allocated_data_ = nullptr ;
354377 data_ = nullptr ;
@@ -357,7 +380,7 @@ std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore() {
357380}
358381
359382Local<ArrayBuffer> ByteSource::ToArrayBuffer (Environment* env) {
360- std::unique_ptr<BackingStore> store = ReleaseToBackingStore ();
383+ std::unique_ptr<BackingStore> store = ReleaseToBackingStore (env );
361384 return ArrayBuffer::New (env->isolate (), std::move (store));
362385}
363386
@@ -648,8 +671,19 @@ namespace {
648671// using OPENSSL_malloc. However, if the secure heap is
649672// initialized, SecureBuffer will automatically use it.
650673void SecureBuffer (const FunctionCallbackInfo<Value>& args) {
651- CHECK (args[0 ]->IsUint32 ());
652674 Environment* env = Environment::GetCurrent (args);
675+ #ifdef V8_ENABLE_SANDBOX
676+ // The v8 sandbox is enabled, so we cannot use the secure heap because
677+ // the sandbox requires that all array buffers be allocated via the isolate.
678+ // That is fundamentally incompatible with the secure heap which allocates
679+ // in openssl's secure heap area. Instead we'll just throw an error here.
680+ //
681+ // That said, we really shouldn't get here in the first place since the
682+ // option to enable the secure heap is only available when the sandbox
683+ // is disabled.
684+ UNREACHABLE ();
685+ #else
686+ CHECK (args[0 ]->IsUint32 ());
653687 uint32_t len = args[0 ].As <Uint32>()->Value ();
654688
655689 auto data = DataPointer::SecureAlloc (len);
@@ -676,6 +710,7 @@ void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
676710
677711 Local<ArrayBuffer> buffer = ArrayBuffer::New (env->isolate (), store);
678712 args.GetReturnValue ().Set (Uint8Array::New (buffer, 0 , len));
713+ #endif // V8_ENABLE_SANDBOX
679714}
680715
681716void SecureHeapUsed (const FunctionCallbackInfo<Value>& args) {
0 commit comments