@@ -34,6 +34,8 @@ using ncrypto::EnginePointer;
34
34
using ncrypto::SSLPointer;
35
35
using v8::ArrayBuffer;
36
36
using v8::BackingStore;
37
+ using v8::BackingStoreInitializationMode;
38
+ using v8::BackingStoreOnFailureMode;
37
39
using v8::BigInt;
38
40
using v8::Context;
39
41
using v8::EscapableHandleScope;
@@ -339,16 +341,37 @@ ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
339
341
return *this ;
340
342
}
341
343
342
- std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore () {
344
+ std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore (
345
+ Environment* env) {
343
346
// It's ok for allocated_data_ to be nullptr but
344
347
// only if size_ is zero.
345
348
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
346
368
std::unique_ptr<BackingStore> ptr = ArrayBuffer::NewBackingStore (
347
369
allocated_data_,
348
370
size (),
349
371
[](void * data, size_t length, void * deleter_data) {
350
372
OPENSSL_clear_free (deleter_data, length);
351
373
}, allocated_data_);
374
+ #endif // V8_ENABLE_SANDBOX
352
375
CHECK (ptr);
353
376
allocated_data_ = nullptr ;
354
377
data_ = nullptr ;
@@ -357,7 +380,7 @@ std::unique_ptr<BackingStore> ByteSource::ReleaseToBackingStore() {
357
380
}
358
381
359
382
Local<ArrayBuffer> ByteSource::ToArrayBuffer (Environment* env) {
360
- std::unique_ptr<BackingStore> store = ReleaseToBackingStore ();
383
+ std::unique_ptr<BackingStore> store = ReleaseToBackingStore (env );
361
384
return ArrayBuffer::New (env->isolate (), std::move (store));
362
385
}
363
386
@@ -648,8 +671,19 @@ namespace {
648
671
// using OPENSSL_malloc. However, if the secure heap is
649
672
// initialized, SecureBuffer will automatically use it.
650
673
void SecureBuffer (const FunctionCallbackInfo<Value>& args) {
651
- CHECK (args[0 ]->IsUint32 ());
652
674
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 ());
653
687
uint32_t len = args[0 ].As <Uint32>()->Value ();
654
688
655
689
auto data = DataPointer::SecureAlloc (len);
@@ -676,6 +710,7 @@ void SecureBuffer(const FunctionCallbackInfo<Value>& args) {
676
710
677
711
Local<ArrayBuffer> buffer = ArrayBuffer::New (env->isolate (), store);
678
712
args.GetReturnValue ().Set (Uint8Array::New (buffer, 0 , len));
713
+ #endif // V8_ENABLE_SANDBOX
679
714
}
680
715
681
716
void SecureHeapUsed (const FunctionCallbackInfo<Value>& args) {
0 commit comments