Commit e0dc3d29 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Reject an exception in the start function on the promise

We assumed that if the ErrorThrower is empty after instantiation, then
instantiation succeeded and an instance exists which we can return.
However, if the start function throws, no instance exists, which caused
a crash. With this CL we handle execeptions thrown by the start
function correctly.


R=clemensh@chromium.org

Bug: chromium:848966
Change-Id: I51dc94e6bc563aa4a4b88c44a14e831af913fbd8
Reviewed-on: https://chromium-review.googlesource.com/1092234Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53687}
parent fcfc8519
......@@ -64,14 +64,36 @@ void WasmEngine::AsyncInstantiate(
Isolate* isolate, std::unique_ptr<InstantiationResultResolver> resolver,
Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports) {
ErrorThrower thrower(isolate, nullptr);
// Instantiate a TryCatch so that caught exceptions won't progagate out.
// They will still be set as pending exceptions on the isolate.
// TODO(clemensh): Avoid TryCatch, use Execution::TryCall internally to invoke
// start function and report thrown exception explicitly via out argument.
v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
catcher.SetVerbose(false);
catcher.SetCaptureMessage(false);
MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate(
isolate, &thrower, module_object, imports, Handle<JSArrayBuffer>::null());
if (!instance_object.is_null()) {
resolver->OnInstantiationSucceeded(instance_object.ToHandleChecked());
return;
}
// We either have a pending exception (if the start function threw), or an
// exception in the ErrorThrower.
DCHECK_EQ(1, isolate->has_pending_exception() + thrower.error());
if (thrower.error()) {
resolver->OnInstantiationFailed(thrower.Reify());
return;
} else {
// The start function has thrown an exception. We have to move the
// exception to the promise chain.
Handle<Object> exception(isolate->pending_exception(), isolate);
isolate->clear_pending_exception();
DCHECK(*isolate->external_caught_exception_address());
*isolate->external_caught_exception_address() = false;
resolver->OnInstantiationFailed(exception);
}
Handle<WasmInstanceObject> instance = instance_object.ToHandleChecked();
resolver->OnInstantiationSucceeded(instance);
}
void WasmEngine::AsyncCompile(
......
......@@ -139,6 +139,10 @@ assertThrows(() => {instantiate(kSig_i_v, [kExprI32Const, 0]);});
builder.addStart(func.index);
assertThrowsEquals(() => builder.instantiate(ffi), error);
assertPromiseResult(builder.asyncInstantiate(ffi), assertUnreachable,
e => assertSame(e, error));
assertPromiseResult(WebAssembly.instantiate(builder.toModule(), ffi),
assertUnreachable, e => assertSame(e, error));
})();
(function testStartFunctionThrowsImplicitly() {
......@@ -149,4 +153,9 @@ assertThrows(() => {instantiate(kSig_i_v, [kExprI32Const, 0]);});
assertThrows(
() => builder.instantiate(), WebAssembly.RuntimeError, /unreachable/);
assertPromiseResult(builder.asyncInstantiate(), assertUnreachable,
e => assertInstanceof(e, WebAssembly.RuntimeError));
assertPromiseResult(WebAssembly.instantiate(builder.toModule()),
assertUnreachable,
e => assertInstanceof(e, WebAssembly.RuntimeError));
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment