Commit c518fd8f authored by Thibaud Michaud's avatar Thibaud Michaud Committed by Commit Bot

[wasm][eh] Update delegate validation rules

The delegate instruction is invalid in the following cases:
- When the target is not a try block or the function block,
- When the instruction is inside a catch handler of the target.

R=clemensb@chromium.org

Bug: v8:8091
Change-Id: Ic59e8314982166863ba2078e2b3b39e3ba488a74
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2656318Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72428}
parent d7b31606
......@@ -2538,12 +2538,18 @@ class WasmFullDecoder : public WasmDecoder<validate> {
return 0;
}
// +1 because the current try block is not included in the count.
uint32_t next_try = imm.depth + 1;
while (next_try < control_depth() && !control_at(next_try)->is_try()) {
next_try++;
Control* target = control_at(imm.depth + 1);
if (imm.depth + 1 < control_depth() - 1 && !target->is_try()) {
this->DecodeError(
"delegate target must be a try block or the function block");
return 0;
}
if (target->is_try_catch() || target->is_try_catchall()) {
this->DecodeError(
"cannot delegate inside the catch handler of the target");
}
FallThruTo(c);
CALL_INTERFACE_IF_PARENT_REACHABLE(Delegate, next_try, c);
CALL_INTERFACE_IF_PARENT_REACHABLE(Delegate, imm.depth + 1, c);
current_code_reachable_ = this->ok() && control_.back().reachable();
EndControl();
PopControl(c);
......
......@@ -765,7 +765,7 @@ class WasmGraphBuildingInterface {
if (block->try_info->might_throw()) {
// Merge the current env into the target handler's env.
SetEnv(block->try_info->catch_env);
if (depth == decoder->control_depth()) {
if (depth == decoder->control_depth() - 1) {
builder_->Rethrow(block->try_info->exception);
builder_->TerminateThrow(effect(), control());
return;
......
......@@ -908,32 +908,6 @@ load("test/mjsunit/wasm/exceptions-utils.js");
assertEquals(1, instance.exports.test(0, 0));
})();
// Delegating to a non-try block should delegate to the next try block down the
// control stack.
(function TestDelegateNonTryBlock() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_v);
let throw_fn = builder.addFunction('throw', kSig_v_v)
.addBody([kExprThrow, except])
.exportFunc();
builder.addFunction('test', kSig_i_v)
.addBody([
kExprTry, kWasmI32,
kExprBlock, kWasmI32,
kExprTry, kWasmI32,
kExprCallFunction, throw_fn.index,
kExprI32Const, 1,
kExprDelegate, 0,
kExprEnd,
kExprCatch, except,
kExprI32Const, 2,
kExprEnd,
]).exportFunc();
instance = builder.instantiate();
assertEquals(2, instance.exports.test());
})();
// Delegate to second enclosing try scope.
(function TestDelegate1() {
print(arguments.callee.name);
......@@ -961,48 +935,6 @@ load("test/mjsunit/wasm/exceptions-utils.js");
assertEquals(3, instance.exports.test());
})();
(function TestDelegateInCatch() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except1 = builder.addException(kSig_v_v);
let except2 = builder.addException(kSig_v_v);
// throw_fn: 0 -> returns
// 1 -> throw except1
// 2 -> throw except2
let throw_fn = builder.addFunction('throw', kSig_v_i)
.addBody([
kExprBlock, kWasmStmt,
kExprBlock, kWasmStmt,
kExprBlock, kWasmStmt,
kExprLocalGet, 0,
kExprBrTable, 2, 0, 1, 2,
kExprEnd,
kExprReturn,
kExprEnd,
kExprThrow, except1,
kExprEnd,
kExprThrow, except2])
.exportFunc();
builder.addFunction('test', kSig_i_i)
.addBody([
kExprTry, kWasmI32,
kExprThrow, except1,
kExprCatch, except1,
kExprTry, kWasmStmt,
kExprLocalGet, 0,
kExprCallFunction, throw_fn.index,
kExprDelegate, 0,
kExprI32Const, 1,
kExprCatch, except2,
kExprI32Const, 2,
kExprEnd,
]).exportFunc();
instance = builder.instantiate();
assertEquals(1, instance.exports.test(0));
assertTraps(WebAssembly.RuntimeError, () => instance.exports.test(1));
assertEquals(2, instance.exports.test(2));
})();
(function TestDelegateUnreachable() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
......
......@@ -2896,15 +2896,22 @@ TEST_F(FunctionBodyDecoderTest, TryDelegate) {
ExpectValidates(sigs.v_v(), {WASM_TRY_OP,
WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0),
kExprCatch, ex, kExprEnd});
ExpectValidates(sigs.v_v(),
{WASM_TRY_OP,
WASM_BLOCK(WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0)),
kExprCatch, ex, kExprEnd});
ExpectValidates(
sigs.v_v(),
{WASM_BLOCK(WASM_TRY_OP, WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 2),
kExprCatch, ex, kExprEnd)});
ExpectFailure(sigs.v_v(),
{WASM_TRY_OP,
WASM_BLOCK(WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0)),
kExprCatch, ex, kExprEnd},
kAppendEnd,
"delegate target must be a try block or the function block");
ExpectFailure(sigs.v_v(),
{WASM_TRY_OP, kExprCatch, ex,
WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0), kExprEnd},
kAppendEnd,
"cannot delegate inside the catch handler of the target");
ExpectFailure(
sigs.v_v(),
{WASM_BLOCK(WASM_TRY_OP, WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 3),
......
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