summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSoni L. <EnderMoneyMod@gmail.com>2024-10-01 19:56:23 -0300
committerGitHub <noreply@github.com>2024-10-01 15:56:23 -0700
commit84ea5d3e3caa92389cec39825cc79140312f6712 (patch)
tree6df506192ee722bb1bf1e36c9e7192a3e62aa4d3
parent790bc0472552d80671bdf99ba7652876c463d526 (diff)
downloadwabt-84ea5d3e3caa92389cec39825cc79140312f6712.tar.gz
wabt-84ea5d3e3caa92389cec39825cc79140312f6712.tar.bz2
wabt-84ea5d3e3caa92389cec39825cc79140312f6712.zip
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 )
-rw-r--r--src/interp/binary-reader-interp.cc22
-rw-r--r--test/regress/interp-ehv3-locals.txt22
2 files changed, 36 insertions, 8 deletions
diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc
index fe988103..f4d05a19 100644
--- a/src/interp/binary-reader-interp.cc
+++ b/src/interp/binary-reader-interp.cc
@@ -831,13 +831,6 @@ Result BinaryReaderInterp::BeginFunctionBody(Index index, Offset size) {
// try-delegate instruction.
PushLabel(LabelKind::Try, Istream::kInvalidOffset, Istream::kInvalidOffset,
func_->handlers.size());
- func_->handlers.push_back(HandlerDesc{HandlerKind::Catch,
- istream_.end(),
- Istream::kInvalidOffset,
- {},
- {Istream::kInvalidOffset},
- static_cast<u32>(func_->locals.size()),
- 0});
return Result::Ok;
}
@@ -856,6 +849,17 @@ Result BinaryReaderInterp::EndFunctionBody(Index index) {
Result BinaryReaderInterp::OnLocalDeclCount(Index count) {
local_decl_count_ = count;
local_count_ = 0;
+ // Continuation of the implicit func label, used for exception handling. (See
+ // BeginFunctionBody.)
+ // We need the local count for this, so we must do it here.
+ // NOTE: we don't count the parameters, as they're not part of the frame.
+ func_->handlers.push_back(HandlerDesc{HandlerKind::Catch,
+ istream_.end(),
+ Istream::kInvalidOffset,
+ {},
+ {Istream::kInvalidOffset},
+ static_cast<u32>(local_decl_count_),
+ 0});
return Result::Ok;
}
@@ -1516,7 +1520,9 @@ Result BinaryReaderInterp::OnTryExpr(Type sig_type) {
u32 exn_stack_height;
CHECK_RESULT(
validator_.GetCatchCount(label_stack_.size() - 1, &exn_stack_height));
- u32 value_stack_height = validator_.type_stack_size();
+ // NOTE: *NOT* GetLocalCount. we don't count the parameters, as they're not
+ // part of the frame.
+ u32 value_stack_height = validator_.type_stack_size() + local_decl_count_;
CHECK_RESULT(validator_.OnTry(GetLocation(), sig_type));
// Push a label that tracks mapping of exn -> catch
PushLabel(LabelKind::Try, Istream::kInvalidOffset, Istream::kInvalidOffset,
diff --git a/test/regress/interp-ehv3-locals.txt b/test/regress/interp-ehv3-locals.txt
new file mode 100644
index 00000000..e4f05c83
--- /dev/null
+++ b/test/regress/interp-ehv3-locals.txt
@@ -0,0 +1,22 @@
+;;; TOOL: run-interp-spec
+;;; ARGS*: --enable-exceptions
+;;; NOTE: ref: issue-2476
+(module
+ (tag $e0)
+ (func (export "broken-local") (result i32)
+ (local $value i32)
+ (try $try
+ (do
+ (local.set $value (i32.const 1))
+ (throw $e0)
+ )
+ (catch $e0)
+ )
+ (local.get $value)
+ )
+)
+
+(assert_return (invoke "broken-local") (i32.const 1))
+(;; STDOUT ;;;
+2/2 tests passed.
+;;; STDOUT ;;)