Skip to content

Commit 84ea5d3

Browse files
authored
wasm-interp: Fix catch handlers' value stack sizes (#2478)
Fixes the value stack size of the catch handler. There were two (related) issues here: - The previous code used `func_->locals.size()` as soon as the function was available, but it hadn't processed the function's locals yet, so it was always empty. (This might not matter in practice, as it's only used by the "function-wide catch handler", which just rethrows.) - The previous code didn't take the function's locals into account when computing the value stack height (relative to the function frame) for a try-catch block. So, it would drop the locals when catching an exception. Closes #2476 (Split from #2470 )
1 parent 790bc04 commit 84ea5d3

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

src/interp/binary-reader-interp.cc

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -831,13 +831,6 @@ Result BinaryReaderInterp::BeginFunctionBody(Index index, Offset size) {
831831
// try-delegate instruction.
832832
PushLabel(LabelKind::Try, Istream::kInvalidOffset, Istream::kInvalidOffset,
833833
func_->handlers.size());
834-
func_->handlers.push_back(HandlerDesc{HandlerKind::Catch,
835-
istream_.end(),
836-
Istream::kInvalidOffset,
837-
{},
838-
{Istream::kInvalidOffset},
839-
static_cast<u32>(func_->locals.size()),
840-
0});
841834
return Result::Ok;
842835
}
843836

@@ -856,6 +849,17 @@ Result BinaryReaderInterp::EndFunctionBody(Index index) {
856849
Result BinaryReaderInterp::OnLocalDeclCount(Index count) {
857850
local_decl_count_ = count;
858851
local_count_ = 0;
852+
// Continuation of the implicit func label, used for exception handling. (See
853+
// BeginFunctionBody.)
854+
// We need the local count for this, so we must do it here.
855+
// NOTE: we don't count the parameters, as they're not part of the frame.
856+
func_->handlers.push_back(HandlerDesc{HandlerKind::Catch,
857+
istream_.end(),
858+
Istream::kInvalidOffset,
859+
{},
860+
{Istream::kInvalidOffset},
861+
static_cast<u32>(local_decl_count_),
862+
0});
859863
return Result::Ok;
860864
}
861865

@@ -1516,7 +1520,9 @@ Result BinaryReaderInterp::OnTryExpr(Type sig_type) {
15161520
u32 exn_stack_height;
15171521
CHECK_RESULT(
15181522
validator_.GetCatchCount(label_stack_.size() - 1, &exn_stack_height));
1519-
u32 value_stack_height = validator_.type_stack_size();
1523+
// NOTE: *NOT* GetLocalCount. we don't count the parameters, as they're not
1524+
// part of the frame.
1525+
u32 value_stack_height = validator_.type_stack_size() + local_decl_count_;
15201526
CHECK_RESULT(validator_.OnTry(GetLocation(), sig_type));
15211527
// Push a label that tracks mapping of exn -> catch
15221528
PushLabel(LabelKind::Try, Istream::kInvalidOffset, Istream::kInvalidOffset,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
;;; TOOL: run-interp-spec
2+
;;; ARGS*: --enable-exceptions
3+
;;; NOTE: ref: issue-2476
4+
(module
5+
(tag $e0)
6+
(func (export "broken-local") (result i32)
7+
(local $value i32)
8+
(try $try
9+
(do
10+
(local.set $value (i32.const 1))
11+
(throw $e0)
12+
)
13+
(catch $e0)
14+
)
15+
(local.get $value)
16+
)
17+
)
18+
19+
(assert_return (invoke "broken-local") (i32.const 1))
20+
(;; STDOUT ;;;
21+
2/2 tests passed.
22+
;;; STDOUT ;;)

0 commit comments

Comments
 (0)