[wasm] Make a few more traps uncatchable
With the upcoming "exception handling" proposal, we have to ensure that traps are not catchable. This patch adds missing "uncatchable" annotations to traps in the C-API and table-related instructions. Fixed: v8:11813 Change-Id: I7bbd5043ede58a5315bd5117eb496ed014e79e91 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2953160 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#75082}
This commit is contained in:
parent
74dde2fce1
commit
f1acce32c5
@ -85,7 +85,6 @@ class V8_NODISCARD ClearThreadInWasmScope {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Object ThrowWasmError(Isolate* isolate, MessageTemplate message) {
|
Object ThrowWasmError(Isolate* isolate, MessageTemplate message) {
|
||||||
HandleScope scope(isolate);
|
|
||||||
Handle<JSObject> error_obj = isolate->factory()->NewWasmRuntimeError(message);
|
Handle<JSObject> error_obj = isolate->factory()->NewWasmRuntimeError(message);
|
||||||
JSObject::AddProperty(isolate, error_obj,
|
JSObject::AddProperty(isolate, error_obj,
|
||||||
isolate->factory()->wasm_uncatchable_symbol(),
|
isolate->factory()->wasm_uncatchable_symbol(),
|
||||||
@ -133,6 +132,7 @@ RUNTIME_FUNCTION(Runtime_WasmMemoryGrow) {
|
|||||||
|
|
||||||
RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
|
RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
|
||||||
ClearThreadInWasmScope flag_scope(isolate);
|
ClearThreadInWasmScope flag_scope(isolate);
|
||||||
|
HandleScope scope(isolate);
|
||||||
DCHECK_EQ(1, args.length());
|
DCHECK_EQ(1, args.length());
|
||||||
CONVERT_SMI_ARG_CHECKED(message_id, 0);
|
CONVERT_SMI_ARG_CHECKED(message_id, 0);
|
||||||
return ThrowWasmError(isolate, MessageTemplateFromInt(message_id));
|
return ThrowWasmError(isolate, MessageTemplateFromInt(message_id));
|
||||||
@ -381,9 +381,7 @@ Object ThrowTableOutOfBounds(Isolate* isolate,
|
|||||||
if (isolate->context().is_null()) {
|
if (isolate->context().is_null()) {
|
||||||
isolate->set_context(instance->native_context());
|
isolate->set_context(instance->native_context());
|
||||||
}
|
}
|
||||||
Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError(
|
return ThrowWasmError(isolate, MessageTemplate::kWasmTrapTableOutOfBounds);
|
||||||
MessageTemplate::kWasmTrapTableOutOfBounds);
|
|
||||||
return isolate->Throw(*error_obj);
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -1006,8 +1006,11 @@ auto Trap::make(Store* store_abs, const Message& message) -> own<Trap> {
|
|||||||
i::Isolate* isolate = store->i_isolate();
|
i::Isolate* isolate = store->i_isolate();
|
||||||
i::HandleScope handle_scope(isolate);
|
i::HandleScope handle_scope(isolate);
|
||||||
i::Handle<i::String> string = VecToString(isolate, message);
|
i::Handle<i::String> string = VecToString(isolate, message);
|
||||||
i::Handle<i::JSReceiver> exception = i::Handle<i::JSReceiver>::cast(
|
i::Handle<i::JSObject> exception =
|
||||||
isolate->factory()->NewError(isolate->error_function(), string));
|
isolate->factory()->NewError(isolate->error_function(), string);
|
||||||
|
i::JSObject::AddProperty(isolate, exception,
|
||||||
|
isolate->factory()->wasm_uncatchable_symbol(),
|
||||||
|
isolate->factory()->true_value(), i::NONE);
|
||||||
return implement<Trap>::type::make(store, exception);
|
return implement<Trap>::type::make(store, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,6 +531,10 @@ void TestTrapNotCaught(byte* code, size_t code_size,
|
|||||||
constexpr uint32_t kResultSuccess = 23;
|
constexpr uint32_t kResultSuccess = 23;
|
||||||
constexpr uint32_t kResultCaught = 47;
|
constexpr uint32_t kResultCaught = 47;
|
||||||
|
|
||||||
|
// Add an indirect function table.
|
||||||
|
const int kTableSize = 2;
|
||||||
|
r.builder().AddIndirectFunctionTable(nullptr, kTableSize);
|
||||||
|
|
||||||
// Build a trapping helper function.
|
// Build a trapping helper function.
|
||||||
WasmFunctionCompiler& trap_func = r.NewFunction(sigs.i_ii());
|
WasmFunctionCompiler& trap_func = r.NewFunction(sigs.i_ii());
|
||||||
trap_func.Build(code, code + code_size);
|
trap_func.Build(code, code + code_size);
|
||||||
@ -574,6 +578,17 @@ WASM_EXEC_TEST(TryCatchTrapRemByZero) {
|
|||||||
TestTrapNotCaught(code, arraysize(code), execution_tier);
|
TestTrapNotCaught(code, arraysize(code), execution_tier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WASM_EXEC_TEST(TryCatchTrapTableFill) {
|
||||||
|
EXPERIMENTAL_FLAG_SCOPE(reftypes);
|
||||||
|
int table_index = 0;
|
||||||
|
int length = 10; // OOB.
|
||||||
|
int start = 10; // OOB.
|
||||||
|
byte code[] = {WASM_TABLE_FILL(table_index, WASM_I32V(length),
|
||||||
|
WASM_REF_NULL(kFuncRefCode), WASM_I32V(start)),
|
||||||
|
WASM_I32V_1(42)};
|
||||||
|
TestTrapNotCaught(code, arraysize(code), execution_tier);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// TODO(cleanup): Define in cctest.h and re-use where appropriate.
|
// TODO(cleanup): Define in cctest.h and re-use where appropriate.
|
||||||
class IsolateScope {
|
class IsolateScope {
|
||||||
|
@ -35,6 +35,7 @@ void ExpectMessage(const char* expected, const Message& message) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_F(WasmCapiTest, Traps) {
|
TEST_F(WasmCapiTest, Traps) {
|
||||||
|
FLAG_experimental_wasm_eh = true;
|
||||||
ValueType i32_type[] = {kWasmI32};
|
ValueType i32_type[] = {kWasmI32};
|
||||||
FunctionSig sig(1, 0, i32_type);
|
FunctionSig sig(1, 0, i32_type);
|
||||||
uint32_t callback_index = builder()->AddImport(CStrVector("callback"), &sig);
|
uint32_t callback_index = builder()->AddImport(CStrVector("callback"), &sig);
|
||||||
@ -48,6 +49,11 @@ TEST_F(WasmCapiTest, Traps) {
|
|||||||
byte code3[] = {WASM_I32V_3(0), WASM_UNREACHABLE, WASM_I32V_1(1)};
|
byte code3[] = {WASM_I32V_3(0), WASM_UNREACHABLE, WASM_I32V_1(1)};
|
||||||
AddFunction(code3, sizeof(code3), &sig);
|
AddFunction(code3, sizeof(code3), &sig);
|
||||||
|
|
||||||
|
// Check that traps returned from a C callback are uncatchable in Wasm.
|
||||||
|
byte code4[] = {WASM_TRY_CATCH_ALL_T(
|
||||||
|
kWasmI32, WASM_CALL_FUNCTION0(callback_index), WASM_I32V(42))};
|
||||||
|
AddExportedFunction(CStrVector("uncatchable"), code4, sizeof(code4), &sig);
|
||||||
|
|
||||||
own<FuncType> func_type =
|
own<FuncType> func_type =
|
||||||
FuncType::make(ownvec<ValType>::make(),
|
FuncType::make(ownvec<ValType>::make(),
|
||||||
ownvec<ValType>::make(ValType::make(::wasm::I32)));
|
ownvec<ValType>::make(ValType::make(::wasm::I32)));
|
||||||
@ -113,6 +119,13 @@ TEST_F(WasmCapiTest, Traps) {
|
|||||||
EXPECT_EQ(2u, frame->func_index());
|
EXPECT_EQ(2u, frame->func_index());
|
||||||
EXPECT_EQ(1u, frame->func_offset());
|
EXPECT_EQ(1u, frame->func_offset());
|
||||||
EXPECT_EQ(func2_offset + frame->func_offset(), frame->module_offset());
|
EXPECT_EQ(func2_offset + frame->func_offset(), frame->module_offset());
|
||||||
|
|
||||||
|
Func* wasm_uncatchable_func = GetExportedFunction(2);
|
||||||
|
Val* args = nullptr;
|
||||||
|
Val results[1] = {Val(3.14)}; // Sentinel value.
|
||||||
|
own<Trap> uncatchable_trap = wasm_uncatchable_func->call(args, results);
|
||||||
|
EXPECT_NE(nullptr, uncatchable_trap.get());
|
||||||
|
EXPECT_EQ(::wasm::F64, results[0].kind());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
|
Loading…
Reference in New Issue
Block a user