@@ -34,6 +34,7 @@ using ncrypto::EnginePointer;
3434using ncrypto::SSLPointer;
3535using v8::ArrayBuffer;
3636using v8::BackingStore;
37+ using v8::BackingStoreInitializationMode;
3738using v8::BigInt;
3839using v8::Context;
3940using v8::EscapableHandleScope;
@@ -339,16 +340,30 @@ ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
339340 return *this ;
340341}
341342
342- std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore () {
343+ std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore (
344+ Environment* env) {
343345 // It's ok for allocated_data_ to be nullptr but
344346 // only if size_ is zero.
345347 CHECK_IMPLIES (size_ > 0 , allocated_data_ != nullptr );
348+ #ifdef V8_ENABLE_SANDBOX
349+ // If the v8 sandbox is enabled, then all array buffers must be allocated
350+ // via the isolate. External buffers are not allowed. So, instead of wrapping
351+ // the allocated data we'll copy it instead.
352+
353+ // TODO(@jasnell): It would be nice to use an abstracted utility to do this
354+ // branch instead of duplicating the V8_ENABLE_SANDBOX check each time.
355+ std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore (
356+ env->isolate (), size (), BackingStoreInitializationMode::kUninitialized );
357+ memcpy (ptr->Data (), allocated_data_, size ());
358+ OPENSSL_clear_free (allocated_data_, size_);
359+ #else
346360 std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore (
347361 allocated_data_,
348362 size (),
349363 [](void * data, size_t length, void * deleter_data) {
350364 OPENSSL_clear_free (deleter_data, length);
351365 }, allocated_data_);
366+ #endif // V8_ENABLE_SANDBOX
352367 CHECK (ptr);
353368 allocated_data_ = nullptr ;
354369 data_ = nullptr ;
@@ -357,7 +372,7 @@ std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore() {
357372}
358373
359374Local<ArrayBuffer> ByteSource::ToArrayBuffer (Environment* env) {
360- std::unique_ptr<BackingStore> store = ReleaseToBackingStore ();
375+ std::unique_ptr<BackingStore> store = ReleaseToBackingStore (env );
361376 return ArrayBuffer::New (env->isolate (), std::move (store));
362377}
363378
@@ -648,8 +663,19 @@ namespace {
648663// using OPENSSL_malloc. However, if the secure heap is
649664// initialized, SecureBuffer will automatically use it.
650665void SecureBuffer (const FunctionCallbackInfo<Value>& args) {
651- CHECK (args[0 ]->IsUint32 ());
652666 Environment* env = Environment::GetCurrent (args);
667+ #ifdef V8_ENABLE_SANDBOX
668+ // The v8 sandbox is enabled, so we cannot use the secure heap because
669+ // the sandbox requires that all array buffers be allocated via the isolate.
670+ // That is fundamentally incompatible with the secure heap which allocates
671+ // in openssl's secure heap area. Instead we'll just throw an error here.
672+ //
673+ // That said, we really shouldn't get here in the first place since the
674+ // option to enable the secure heap is only available when the sandbox
675+ // is disabled.
676+ THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION (env);
677+ #else
678+ CHECK (args[0 ]->IsUint32 ());
653679 uint32_t len = args[0 ].As <Uint32>()->Value ();
654680
655681 auto data = DataPointer::SecureAlloc (len);
@@ -676,6 +702,7 @@ void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
676702
677703 Local<ArrayBuffer> buffer = ArrayBuffer::New (env->isolate (), store);
678704 args.GetReturnValue ().Set (Uint8Array::New (buffer, 0 , len));
705+ #endif // V8_ENABLE_SANDBOX
679706}
680707
681708void SecureHeapUsed (const FunctionCallbackInfo<Value>& args) {
0 commit comments