Index: src/wasm/wasm-js.cc |
diff --git a/src/wasm/wasm-js.cc b/src/wasm/wasm-js.cc |
index 91d6c8a51c74d93443c808972aabc134ef58c4b3..a3a42cdc99f7af64952099a2b21cc9c839f7f6f8 100644 |
--- a/src/wasm/wasm-js.cc |
+++ b/src/wasm/wasm-js.cc |
@@ -31,6 +31,11 @@ using v8::internal::wasm::ErrorThrower; |
namespace v8 { |
namespace { |
+ |
+#define RANGE_ERROR_MSG \ |
+ "Wasm compilation exceeds internal limits in this context for the provided " \ |
+ "arguments" |
+ |
// TODO(wasm): move brand check to the respective types, and don't throw |
// in it, rather, use a provided ErrorThrower, or let caller handle it. |
static bool HasBrand(i::Handle<i::Object> value, i::Handle<i::Symbol> sym) { |
@@ -73,6 +78,44 @@ i::MaybeHandle<i::WasmModuleObject> GetFirstArgumentAsModule( |
v8::Utils::OpenHandle(*module_obj)); |
} |
+bool IsCompilationAllowed(i::Isolate* isolate, ErrorThrower* thrower, |
+ v8::Local<v8::Value> source, bool is_async) { |
+ // Allow caller to do one final check on thrower state, rather than |
+ // one at each step. No information is lost - failure reason is captured |
+ // in the thrower state. |
+ if (thrower->error()) return false; |
+ |
+ AllowWasmCompileCallback callback = isolate->allow_wasm_compile_callback(); |
+ if (callback != nullptr && |
+ !callback(reinterpret_cast<v8::Isolate*>(isolate), source, is_async)) { |
+ thrower->RangeError(RANGE_ERROR_MSG); |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+bool IsInstantiationAllowed(i::Isolate* isolate, ErrorThrower* thrower, |
+ v8::Local<v8::Value> module_or_bytes, |
+ i::MaybeHandle<i::JSReceiver> ffi, bool is_async) { |
+ // Allow caller to do one final check on thrower state, rather than |
+ // one at each step. No information is lost - failure reason is captured |
+ // in the thrower state. |
+ if (thrower->error()) return false; |
+ v8::MaybeLocal<v8::Value> v8_ffi; |
+ if (!ffi.is_null()) { |
+ v8_ffi = v8::Local<v8::Value>::Cast(Utils::ToLocal(ffi.ToHandleChecked())); |
+ } |
+ AllowWasmInstantiateCallback callback = |
+ isolate->allow_wasm_instantiate_callback(); |
+ if (callback != nullptr && |
+ !callback(reinterpret_cast<v8::Isolate*>(isolate), module_or_bytes, |
+ v8_ffi, is_async)) { |
+ thrower->RangeError(RANGE_ERROR_MSG); |
+ return false; |
+ } |
+ return true; |
+} |
+ |
i::wasm::ModuleWireBytes GetFirstArgumentAsBytes( |
const v8::FunctionCallbackInfo<v8::Value>& args, ErrorThrower* thrower) { |
if (args.Length() < 1) { |
@@ -139,10 +182,11 @@ void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { |
return_value.Set(resolver->GetPromise()); |
auto bytes = GetFirstArgumentAsBytes(args, &thrower); |
- if (thrower.error()) { |
+ if (!IsCompilationAllowed(i_isolate, &thrower, args[0], true)) { |
resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
return; |
} |
+ DCHECK(!thrower.error()); |
i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise()); |
i::wasm::AsyncCompile(i_isolate, promise, bytes); |
} |
@@ -175,8 +219,9 @@ void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
ErrorThrower thrower(i_isolate, "WebAssembly.Module()"); |
auto bytes = GetFirstArgumentAsBytes(args, &thrower); |
- if (thrower.error()) return; |
+ if (!IsCompilationAllowed(i_isolate, &thrower, args[0], false)) return; |
+ DCHECK(!thrower.error()); |
i::MaybeHandle<i::Object> module_obj = |
i::wasm::SyncCompile(i_isolate, &thrower, bytes); |
if (module_obj.is_null()) return; |
@@ -251,7 +296,11 @@ void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { |
if (thrower.error()) return; |
auto maybe_imports = GetSecondArgumentAsImports(args, &thrower); |
- if (thrower.error()) return; |
+ if (!IsInstantiationAllowed(i_isolate, &thrower, args[0], maybe_imports, |
+ false)) { |
+ return; |
+ } |
+ DCHECK(!thrower.error()); |
i::MaybeHandle<i::Object> instance_object = i::wasm::SyncInstantiate( |
i_isolate, &thrower, maybe_module.ToHandleChecked(), maybe_imports, |
@@ -299,8 +348,12 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
return; |
} |
+ if (!IsInstantiationAllowed(i_isolate, &thrower, args[0], maybe_imports, |
+ true)) { |
+ resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
+ return; |
+ } |
i::Handle<i::JSPromise> promise = Utils::OpenHandle(*resolver->GetPromise()); |
- |
if (HasBrand(first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym()))) { |
// WebAssembly.instantiate(module, imports) -> WebAssembly.Instance |
auto module_object = GetFirstArgumentAsModule(args, &thrower); |