[wasm][eh] Make stack overflows uncatchable

R=jkummerow@chromium.org

Change-Id: Ibc772d81765e10331fa8753e8b7dfd3d18509819
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2859864
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74333}
This commit is contained in:
Thibaud Michaud 2021-05-03 16:29:06 +02:00 committed by V8 LUCI CQ
parent d6fa333dda
commit 620da72cef
4 changed files with 82 additions and 4 deletions

View File

@ -1404,11 +1404,13 @@ Object Isolate::StackOverflow() {
MessageFormatter::TemplateString(MessageTemplate::kStackOverflow));
Handle<Object> options = factory()->undefined_value();
Handle<Object> no_caller;
Handle<Object> exception;
Handle<JSObject> exception;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
this, exception,
ErrorUtils::Construct(this, fun, fun, msg, options, SKIP_NONE, no_caller,
ErrorUtils::StackTraceCollection::kSimple));
JSObject::AddProperty(this, exception, factory()->wasm_uncatchable_symbol(),
factory()->true_value(), NONE);
Throw(*exception);

View File

@ -574,6 +574,64 @@ WASM_EXEC_TEST(TryCatchTrapRemByZero) {
TestTrapNotCaught(code, arraysize(code), execution_tier);
}
namespace {
// TODO(cleanup): Define in cctest.h and re-use where appropriate.
class IsolateScope {
public:
IsolateScope() {
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
isolate_ = v8::Isolate::New(create_params);
isolate_->Enter();
}
~IsolateScope() {
isolate_->Exit();
isolate_->Dispose();
}
v8::Isolate* isolate() { return isolate_; }
Isolate* i_isolate() { return reinterpret_cast<Isolate*>(isolate_); }
private:
v8::Isolate* isolate_;
};
} // namespace
UNINITIALIZED_WASM_EXEC_TEST(TestStackOverflowNotCaught) {
TestSignatures sigs;
EXPERIMENTAL_FLAG_SCOPE(eh);
// FLAG_stack_size must be set before isolate initialization.
FlagScope<int32_t> stack_size(&v8::internal::FLAG_stack_size, 8);
IsolateScope isolate_scope;
LocalContext context(isolate_scope.isolate());
WasmRunner<uint32_t> r(execution_tier, nullptr, "main",
kRuntimeExceptionSupport, isolate_scope.i_isolate());
// Build a function that calls itself until stack overflow.
WasmFunctionCompiler& stack_overflow = r.NewFunction(sigs.v_v());
byte stack_overflow_code[] = {kExprCallFunction,
stack_overflow.function_index()};
stack_overflow.Build(stack_overflow_code,
stack_overflow_code + arraysize(stack_overflow_code));
// Build the main test function.
BUILD(r, WASM_TRY_CATCH_ALL_T(kWasmI32,
WASM_STMTS(WASM_I32V(1), kExprCallFunction,
stack_overflow.function_index()),
WASM_STMTS(WASM_I32V(1))));
if (execution_tier != TestExecutionTier::kInterpreter) {
// Need to call through JS to allow for creation of stack traces.
r.CheckCallViaJSTraps();
} else {
constexpr int stopped = 0;
CHECK_EQ(stopped, r.CallInterpreter());
}
}
TEST(Regress1180457) {
TestSignatures sigs;
EXPERIMENTAL_FLAG_SCOPE(eh);

View File

@ -3106,9 +3106,6 @@ class WasmInterpreterInternals {
// it to 0 here such that we report the same position as in compiled code.
frames_.back().pc = 0;
isolate_->StackOverflow();
if (FLAG_experimental_wasm_eh) {
possible_nondeterminism_ = true;
}
if (HandleException(isolate_) == WasmInterpreter::HANDLED) {
ReloadFromFrameOnException(decoder, target, pc, limit);
return true;

View File

@ -263,6 +263,27 @@ load("test/mjsunit/wasm/exceptions-utils.js");
assertInstanceof(caught.__proto__, WebAssembly.RuntimeError);
})();
(function TestStackOverflowNotCaught() {
print(arguments.callee.name);
function stack_overflow() {
%ThrowStackOverflow();
}
let builder = new WasmModuleBuilder();
let sig_v_v = builder.addType(kSig_v_v);
let kStackOverflow = builder.addImport('', 'stack_overflow', sig_v_v);
builder.addFunction('try_stack_overflow', kSig_v_v)
.addBody([
kExprTry, kWasmVoid,
kExprCallFunction, 0,
kExprCatchAll,
kExprEnd
]).exportFunc();
let instance = builder.instantiate({'': {'stack_overflow': stack_overflow}});
assertThrows(() => instance.exports.try_stack_overflow(),
RangeError, 'Maximum call stack size exceeded');
})();
// Test that we can distinguish which exception was thrown by using a cascaded
// sequence of nested try blocks with a single catch block each.
(function TestCatchComplex1() {