diff --git a/include/capi/cef_v8_capi.h b/include/capi/cef_v8_capi.h index 4e74d9e46..596da0434 100644 --- a/include/capi/cef_v8_capi.h +++ b/include/capi/cef_v8_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=5dd4948a92af2ad69e2171f2dffb8f2c23e5c147$ +// $hash=0b56c483bee6489e591c54c9dbb0940cd3098eaa$ // #ifndef CEF_INCLUDE_CAPI_CEF_V8_CAPI_H_ @@ -832,11 +832,24 @@ CEF_EXPORT cef_v8value_t* cef_v8value_create_array(int length); /// cef_v8handler_t or cef_v8accessor_t callback, or in combination with calling /// enter() and exit() on a stored cef_v8context_t reference. /// +/// NOTE: Always returns nullptr when V8 sandbox is enabled. +/// CEF_EXPORT cef_v8value_t* cef_v8value_create_array_buffer( void* buffer, size_t length, cef_v8array_buffer_release_callback_t* release_callback); +/// +/// Create a new cef_v8value_t object of type ArrayBuffer which copies the +/// provided |buffer| of size |length| bytes. This function should only be +/// called from within the scope of a cef_render_process_handler_t, +/// cef_v8handler_t or cef_v8accessor_t callback, or in combination with calling +/// enter() and exit() on a stored cef_v8context_t reference. +/// +CEF_EXPORT cef_v8value_t* cef_v8value_create_array_buffer_with_copy( + void* buffer, + size_t length); + /// /// Create a new cef_v8value_t object of type function. This function should /// only be called from within the scope of a cef_render_process_handler_t, diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h index 846ed4ede..000f6be98 100644 --- a/include/cef_api_hash.h +++ b/include/cef_api_hash.h @@ -42,13 +42,13 @@ // way that may cause binary incompatibility with other builds. The universal // hash value will change if any platform is affected whereas the platform hash // values will change only if that particular platform is affected. -#define CEF_API_HASH_UNIVERSAL "316cc23ff49e0d0962090cbfb0a0279ce3dc3c50" +#define CEF_API_HASH_UNIVERSAL "80fd8337eb375cb48d617cd7cf01b531ea577efc" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "66c126d91698670af3835a707a84ce4dbb4a16fa" +#define CEF_API_HASH_PLATFORM "81d92ace6598de3106b212d70454022678fb2e2b" #elif defined(OS_MAC) -#define CEF_API_HASH_PLATFORM "c1d8d20920c3a3e13a6a6efef51b2b775f69d2c7" +#define CEF_API_HASH_PLATFORM "c7b1f631ac53d876ea88f60a7f768b8f1ad1f0d8" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "7ccfa4c608c16a4f8bedc97a2bdf50729784c5ee" +#define CEF_API_HASH_PLATFORM "8dc9b5f33e800f9ac83253d6c7d714952ba8fa85" #endif #ifdef __cplusplus diff --git a/include/cef_v8.h b/include/cef_v8.h index 520444cb5..151f46ebc 100644 --- a/include/cef_v8.h +++ b/include/cef_v8.h @@ -520,12 +520,26 @@ class CefV8Value : public virtual CefBaseRefCounted { /// or CefV8Accessor callback, or in combination with calling Enter() and /// Exit() on a stored CefV8Context reference. /// + /// NOTE: Always returns nullptr when V8 sandbox is enabled. + /// /*--cef(optional_param=buffer)--*/ static CefRefPtr CreateArrayBuffer( void* buffer, size_t length, CefRefPtr release_callback); + /// + /// Create a new CefV8Value object of type ArrayBuffer which copies the + /// provided |buffer| of size |length| bytes. + /// This method should only be called from within the scope of a + /// CefRenderProcessHandler, CefV8Handler or CefV8Accessor callback, or in + /// combination with calling Enter() and Exit() on a stored CefV8Context + /// reference. + /// + /*--cef(optional_param=buffer)--*/ + static CefRefPtr CreateArrayBufferWithCopy(void* buffer, + size_t length); + /// /// Create a new CefV8Value object of type function. This method should only /// be called from within the scope of a CefRenderProcessHandler, CefV8Handler diff --git a/libcef/renderer/v8_impl.cc b/libcef/renderer/v8_impl.cc index 723e80519..eb326e9f4 100644 --- a/libcef/renderer/v8_impl.cc +++ b/libcef/renderer/v8_impl.cc @@ -1412,6 +1412,7 @@ CefRefPtr CefV8Value::CreateArrayBuffer( void* buffer, size_t length, CefRefPtr release_callback) { +#ifndef V8_ENABLE_SANDBOX CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr); v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate(); @@ -1451,6 +1452,46 @@ CefRefPtr CefV8Value::CreateArrayBuffer( CefRefPtr impl = new CefV8ValueImpl(isolate); impl->InitObject(ab, tracker); return impl.get(); +#else + LOG(ERROR) + << "CefV8Value::CreateArrayBuffer is not supported with the V8 " + "sandbox enabled, use CefV8Value::CreateArrayBufferWithCopy instead"; + return nullptr; +#endif // V8_ENABLE_SANDBOX +} + +// static +CefRefPtr CefV8Value::CreateArrayBufferWithCopy(void* buffer, + size_t length) { + CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr); + + v8::Isolate* isolate = CefV8IsolateManager::Get()->isolate(); + v8::HandleScope handle_scope(isolate); + v8::Local context = isolate->GetCurrentContext(); + if (context.IsEmpty()) { + DCHECK(false) << "not currently in a V8 context"; + return nullptr; + } + + // Create a tracker object that will cause the user data reference to be + // released when the V8 object is destroyed. + V8TrackObject* tracker = new V8TrackObject(isolate); + + v8::Local ab = v8::ArrayBuffer::New( + isolate, length, v8::BackingStoreInitializationMode::kUninitialized); + + if (length > 0) { + DCHECK(ab->Data()); + DCHECK(buffer); + memcpy(ab->Data(), buffer, length); + } + + // Attach the tracker object. + tracker->AttachTo(context, ab); + + CefRefPtr impl = new CefV8ValueImpl(isolate); + impl->InitObject(ab, tracker); + return impl; } // static diff --git a/libcef_dll/cpptoc/v8value_cpptoc.cc b/libcef_dll/cpptoc/v8value_cpptoc.cc index 97f4dec0e..78389e362 100644 --- a/libcef_dll/cpptoc/v8value_cpptoc.cc +++ b/libcef_dll/cpptoc/v8value_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=c59808566c2a9f2d204b6724bb5a905aeb0e7620$ +// $hash=befb2f29af8a0e8eabf745fad126ebad5a741c74$ // #include "libcef_dll/cpptoc/v8value_cpptoc.h" @@ -155,6 +155,21 @@ CEF_EXPORT cef_v8value_t* cef_v8value_create_array_buffer( return CefV8ValueCppToC::Wrap(_retval); } +CEF_EXPORT cef_v8value_t* cef_v8value_create_array_buffer_with_copy( + void* buffer, + size_t length) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: buffer + + // Execute + CefRefPtr _retval = + CefV8Value::CreateArrayBufferWithCopy(buffer, length); + + // Return type: refptr_same + return CefV8ValueCppToC::Wrap(_retval); +} + CEF_EXPORT cef_v8value_t* cef_v8value_create_function( const cef_string_t* name, cef_v8handler_t* handler) { diff --git a/libcef_dll/ctocpp/v8value_ctocpp.cc b/libcef_dll/ctocpp/v8value_ctocpp.cc index d073d0881..b400f6b59 100644 --- a/libcef_dll/ctocpp/v8value_ctocpp.cc +++ b/libcef_dll/ctocpp/v8value_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=856fc6c190d0e3376824564155618e468764e841$ +// $hash=df9571f843ed0e55e581dc6282079803e3641d2c$ // #include "libcef_dll/ctocpp/v8value_ctocpp.h" @@ -164,6 +164,21 @@ CefRefPtr CefV8Value::CreateArrayBuffer( return CefV8ValueCToCpp::Wrap(_retval); } +NO_SANITIZE("cfi-icall") +CefRefPtr CefV8Value::CreateArrayBufferWithCopy(void* buffer, + size_t length) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: buffer + + // Execute + cef_v8value_t* _retval = + cef_v8value_create_array_buffer_with_copy(buffer, length); + + // Return type: refptr_same + return CefV8ValueCToCpp::Wrap(_retval); +} + NO_SANITIZE("cfi-icall") CefRefPtr CefV8Value::CreateFunction( const CefString& name, diff --git a/libcef_dll/wrapper/cef_message_router.cc b/libcef_dll/wrapper/cef_message_router.cc index d095097bb..4bb9d95c4 100644 --- a/libcef_dll/wrapper/cef_message_router.cc +++ b/libcef_dll/wrapper/cef_message_router.cc @@ -1070,11 +1070,15 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { CefRefPtr context = GetContextByID(context_id); if (context && info->success_callback && context->Enter()) { - CefRefPtr release_callback = - new cmru::BinaryValueABRCallback(response); - - CefRefPtr value = CefV8Value::CreateArrayBuffer( - response->GetData(), response->GetSize(), release_callback); + CefRefPtr value; +#ifdef CEF_V8_ENABLE_SANDBOX + value = CefV8Value::CreateArrayBufferWithCopy(response->GetData(), + response->GetSize()); +#else + value = CefV8Value::CreateArrayBuffer( + response->GetData(), response->GetSize(), + new cmru::BinaryValueABRCallback(response)); +#endif context->Exit(); diff --git a/libcef_dll/wrapper/cef_message_router_utils.h b/libcef_dll/wrapper/cef_message_router_utils.h index b12a98277..6b90ba4b1 100644 --- a/libcef_dll/wrapper/cef_message_router_utils.h +++ b/libcef_dll/wrapper/cef_message_router_utils.h @@ -48,6 +48,7 @@ struct RendererMessage { std::variant> payload; }; +#ifndef CEF_V8_ENABLE_SANDBOX class BinaryValueABRCallback final : public CefV8ArrayBufferReleaseCallback { public: explicit BinaryValueABRCallback(CefRefPtr value) @@ -62,6 +63,7 @@ class BinaryValueABRCallback final : public CefV8ArrayBufferReleaseCallback { IMPLEMENT_REFCOUNTING(BinaryValueABRCallback); }; +#endif CefRefPtr CreateBrowserResponseBuilder( size_t threshold, diff --git a/libcef_dll/wrapper/libcef_dll_dylib.cc b/libcef_dll/wrapper/libcef_dll_dylib.cc index 260de63b8..efe941e1d 100644 --- a/libcef_dll/wrapper/libcef_dll_dylib.cc +++ b/libcef_dll/wrapper/libcef_dll_dylib.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=fd61a77bd549fb94bba963f9c0737ebceac324ac$ +// $hash=85864cf7616899c4d51fbaf995d8e0db55249bd7$ // #include @@ -209,6 +209,8 @@ struct libcef_pointers { decltype(&cef_v8value_create_object) cef_v8value_create_object; decltype(&cef_v8value_create_array) cef_v8value_create_array; decltype(&cef_v8value_create_array_buffer) cef_v8value_create_array_buffer; + decltype(&cef_v8value_create_array_buffer_with_copy) + cef_v8value_create_array_buffer_with_copy; decltype(&cef_v8value_create_function) cef_v8value_create_function; decltype(&cef_v8value_create_promise) cef_v8value_create_promise; decltype(&cef_v8stack_trace_get_current) cef_v8stack_trace_get_current; @@ -439,6 +441,7 @@ int libcef_init_pointers(const char* path) { INIT_ENTRY(cef_v8value_create_object); INIT_ENTRY(cef_v8value_create_array); INIT_ENTRY(cef_v8value_create_array_buffer); + INIT_ENTRY(cef_v8value_create_array_buffer_with_copy); INIT_ENTRY(cef_v8value_create_function); INIT_ENTRY(cef_v8value_create_promise); INIT_ENTRY(cef_v8stack_trace_get_current); @@ -1145,6 +1148,14 @@ struct _cef_v8value_t* cef_v8value_create_array_buffer( release_callback); } +NO_SANITIZE("cfi-icall") +struct _cef_v8value_t* cef_v8value_create_array_buffer_with_copy( + void* buffer, + size_t length) { + return g_libcef_pointers.cef_v8value_create_array_buffer_with_copy(buffer, + length); +} + NO_SANITIZE("cfi-icall") struct _cef_v8value_t* cef_v8value_create_function( const cef_string_t* name, diff --git a/tests/cefclient/renderer/performance_test_tests.cc b/tests/cefclient/renderer/performance_test_tests.cc index 4ce76db9e..1d567b21f 100644 --- a/tests/cefclient/renderer/performance_test_tests.cc +++ b/tests/cefclient/renderer/performance_test_tests.cc @@ -322,6 +322,7 @@ PERF_TEST_FUNC(V8ObjectGetValueWithAccessor) { PERF_ITERATIONS_END() } +#ifndef CEF_V8_ENABLE_SANDBOX PERF_TEST_FUNC(V8ArrayBufferCreate) { class ReleaseCallback : public CefV8ArrayBufferReleaseCallback { public: @@ -339,6 +340,17 @@ PERF_TEST_FUNC(V8ArrayBufferCreate) { CefV8Value::CreateArrayBuffer(buffer, byte_len, callback); PERF_ITERATIONS_END() } +#endif // CEF_V8_ENABLE_SANDBOX + +PERF_TEST_FUNC(V8ArrayBufferCopy) { + constexpr size_t len = 1; + constexpr size_t byte_len = len * sizeof(float); + std::array buffer = {0}; + PERF_ITERATIONS_START() + CefRefPtr ret = + CefV8Value::CreateArrayBufferWithCopy(buffer.data(), byte_len); + PERF_ITERATIONS_END() +} PERF_TEST_FUNC(V8ContextEnterExit) { CefRefPtr context = CefV8Context::GetCurrentContext(); @@ -385,7 +397,10 @@ const PerfTestEntry kPerfTests[] = { PERF_TEST_ENTRY(V8ObjectGetValue), PERF_TEST_ENTRY(V8ObjectSetValueWithAccessor), PERF_TEST_ENTRY(V8ObjectGetValueWithAccessor), +#ifndef CEF_V8_ENABLE_SANDBOX PERF_TEST_ENTRY(V8ArrayBufferCreate), +#endif // CEF_V8_ENABLE_SANDBOX + PERF_TEST_ENTRY(V8ArrayBufferCopy), PERF_TEST_ENTRY(V8ContextEnterExit), PERF_TEST_ENTRY(V8ContextEval), }; diff --git a/tests/cefclient/resources/binary_transfer.html b/tests/cefclient/resources/binary_transfer.html index 947769e99..fa07d0448 100644 --- a/tests/cefclient/resources/binary_transfer.html +++ b/tests/cefclient/resources/binary_transfer.html @@ -3,11 +3,12 @@ Binary vs String Transfer Benchmark - +