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