[wasm] Fix crash during exception stack unwinding.

This fixes a crash with a predicate used during stack unwinding of
WebAssembly frames during exception handling. The predicate caused an
observable side-effect in JavaScript during unwinding, code that is
inherently unhandlified and is not allowed to be observable.

The fix actually just removes the entire predicate. This is because the
updated proposal causes all JavaScript exceptions to participate in
WebAssembly exception handling, allowing modelling of "finally" language
constructs to perform cleanup independent of the embedders exception
details.

R=ahaas@chromium.org
TEST=mjsunit/regress/wasm/regress-8095
BUG=v8:8095

Change-Id: Ic03bc45e7b7f4562a431ccf910ee9ddcf558aa48
Reviewed-on: https://chromium-review.googlesource.com/1193445
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55457}
This commit is contained in:
Michael Starzinger 2018-08-28 14:18:47 +02:00 committed by Commit Bot
parent e36b49bdb7
commit dd40b33371
3 changed files with 29 additions and 19 deletions

View File

@ -1124,19 +1124,6 @@ void ReportBootstrappingException(Handle<Object> exception,
#endif #endif
} }
bool Isolate::is_catchable_by_wasm(Object* exception) {
// TODO(titzer): thread WASM features here, or just remove this check?
if (!FLAG_experimental_wasm_eh) return false;
if (!is_catchable_by_javascript(exception) || !exception->IsJSError())
return false;
HandleScope scope(this);
Handle<Object> exception_handle(exception, this);
return JSReceiver::HasProperty(Handle<JSReceiver>::cast(exception_handle),
factory()->InternalizeUtf8String(
wasm::WasmException::kRuntimeIdStr))
.IsJust();
}
Object* Isolate::Throw(Object* raw_exception, MessageLocation* location) { Object* Isolate::Throw(Object* raw_exception, MessageLocation* location) {
DCHECK(!has_pending_exception()); DCHECK(!has_pending_exception());
@ -1310,11 +1297,10 @@ Object* Isolate::UnwindAndFindHandler() {
trap_handler::ClearThreadInWasm(); trap_handler::ClearThreadInWasm();
} }
if (!is_catchable_by_wasm(exception)) { // For WebAssembly frames we perform a lookup in the handler table.
break; if (!catchable_by_js) break;
}
int stack_slots = 0; // Will contain stack slot count of frame.
WasmCompiledFrame* wasm_frame = static_cast<WasmCompiledFrame*>(frame); WasmCompiledFrame* wasm_frame = static_cast<WasmCompiledFrame*>(frame);
int stack_slots = 0; // Will contain stack slot count of frame.
int offset = wasm_frame->LookupExceptionHandlerInTable(&stack_slots); int offset = wasm_frame->LookupExceptionHandlerInTable(&stack_slots);
if (offset < 0) break; if (offset < 0) break;
// Compute the stack pointer from the frame pointer. This ensures that // Compute the stack pointer from the frame pointer. This ensures that
@ -1324,7 +1310,7 @@ Object* Isolate::UnwindAndFindHandler() {
stack_slots * kPointerSize; stack_slots * kPointerSize;
// This is going to be handled by Wasm, so we need to set the TLS flag // This is going to be handled by Wasm, so we need to set the TLS flag
// again. // again. It was cleared above assuming the frame would be unwound.
trap_handler::SetThreadInWasm(); trap_handler::SetThreadInWasm();
set_wasm_caught_exception(exception); set_wasm_caught_exception(exception);

View File

@ -757,7 +757,6 @@ class Isolate : private HiddenFactory {
bool IsExternalHandlerOnTop(Object* exception); bool IsExternalHandlerOnTop(Object* exception);
inline bool is_catchable_by_javascript(Object* exception); inline bool is_catchable_by_javascript(Object* exception);
bool is_catchable_by_wasm(Object* exception);
// JS execution stack (see frames.h). // JS execution stack (see frames.h).
static Address c_entry_fp(ThreadLocalTop* thread) { static Address c_entry_fp(ThreadLocalTop* thread) {

View File

@ -0,0 +1,25 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-wasm --experimental-wasm-eh
load("test/mjsunit/wasm/wasm-constants.js");
load("test/mjsunit/wasm/wasm-module-builder.js");
// Prepare a special error object to throw.
var error = new Error("my error");
error.__proto__ = new Proxy(new Error(), {
has(target, property, receiver) {
assertUnreachable();
}
});
// Throw it through a WebAssembly module.
var builder = new WasmModuleBuilder();
builder.addImport('mod', 'fun', kSig_v_v);
builder.addFunction("funnel", kSig_v_v)
.addBody([kExprCallFunction, 0])
.exportFunc();
var instance = builder.instantiate({ mod: {fun: function() { throw error }}});
assertThrows(instance.exports.funnel, Error);