Skip to content

Commit e1d84ff

Browse files
authored
wasm-interp: Fix catch handlers correctly (#2483)
local decl count != local count
1 parent 7d229cf commit e1d84ff

File tree

8 files changed

+40
-16
lines changed

8 files changed

+40
-16
lines changed

include/wabt/binary-reader-logging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
130130
Result BeginFunctionBody(Index index, Offset size) override;
131131
Result OnLocalDeclCount(Index count) override;
132132
Result OnLocalDecl(Index decl_index, Index count, Type type) override;
133+
Result EndLocalDecls() override;
133134

134135
Result OnOpcode(Opcode opcode) override;
135136
Result OnOpcodeBare() override;

include/wabt/binary-reader-nop.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
172172
Result OnLocalDecl(Index decl_index, Index count, Type type) override {
173173
return Result::Ok;
174174
}
175+
Result EndLocalDecls() override { return Result::Ok; }
175176

176177
/* Function expressions; called between BeginFunctionBody and
177178
EndFunctionBody */

include/wabt/binary-reader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ class BinaryReaderDelegate {
188188
virtual Result BeginFunctionBody(Index index, Offset size) = 0;
189189
virtual Result OnLocalDeclCount(Index count) = 0;
190190
virtual Result OnLocalDecl(Index decl_index, Index count, Type type) = 0;
191+
virtual Result EndLocalDecls() = 0;
191192

192193
/* Function expressions; called between BeginFunctionBody and
193194
EndFunctionBody */

src/binary-reader-logging.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ DEFINE_BEGIN(BeginCodeSection)
795795
DEFINE_INDEX(OnFunctionBodyCount)
796796
DEFINE_INDEX(EndFunctionBody)
797797
DEFINE_INDEX(OnLocalDeclCount)
798+
DEFINE0(EndLocalDecls)
798799
DEFINE_LOAD_STORE_OPCODE(OnAtomicLoadExpr);
799800
DEFINE_LOAD_STORE_OPCODE(OnAtomicRmwExpr);
800801
DEFINE_LOAD_STORE_OPCODE(OnAtomicRmwCmpxchgExpr);

src/binary-reader.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2815,6 +2815,7 @@ Result BinaryReader::ReadCodeSection(Offset section_size) {
28152815
ERROR_UNLESS(IsConcreteType(local_type), "expected valid local type");
28162816
CALLBACK(OnLocalDecl, k, num_local_types, local_type);
28172817
}
2818+
CALLBACK(EndLocalDecls);
28182819

28192820
if (options_.skip_function_bodies) {
28202821
state_.offset = end_offset;

src/interp/binary-reader-interp.cc

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
147147
Result BeginFunctionBody(Index index, Offset size) override;
148148
Result OnLocalDeclCount(Index count) override;
149149
Result OnLocalDecl(Index decl_index, Index count, Type type) override;
150+
Result EndLocalDecls() override;
150151

151152
Result OnOpcode(Opcode Opcode) override;
152153
Result OnAtomicLoadExpr(Opcode opcode,
@@ -849,17 +850,6 @@ Result BinaryReaderInterp::EndFunctionBody(Index index) {
849850
Result BinaryReaderInterp::OnLocalDeclCount(Index count) {
850851
local_decl_count_ = count;
851852
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});
863853
return Result::Ok;
864854
}
865855

@@ -870,10 +860,26 @@ Result BinaryReaderInterp::OnLocalDecl(Index decl_index,
870860

871861
local_count_ += count;
872862
func_->locals.push_back(LocalDesc{type, count, local_count_});
863+
return Result::Ok;
864+
}
873865

874-
if (decl_index == local_decl_count_ - 1) {
866+
Result BinaryReaderInterp::EndLocalDecls() {
867+
if (local_count_ != 0) {
875868
istream_.Emit(Opcode::InterpAlloca, local_count_);
876869
}
870+
// Continuation of the implicit func label, used for exception handling. (See
871+
// BeginFunctionBody.)
872+
// We need the local count for this, which is only available after processing
873+
// all local decls.
874+
// NOTE: we don't count the parameters, as they're not part of the frame.
875+
func_->handlers.push_back(HandlerDesc{HandlerKind::Catch,
876+
istream_.end(),
877+
Istream::kInvalidOffset,
878+
{},
879+
{Istream::kInvalidOffset},
880+
static_cast<u32>(local_count_),
881+
0});
882+
877883
return Result::Ok;
878884
}
879885

@@ -1522,7 +1528,7 @@ Result BinaryReaderInterp::OnTryExpr(Type sig_type) {
15221528
validator_.GetCatchCount(label_stack_.size() - 1, &exn_stack_height));
15231529
// NOTE: *NOT* GetLocalCount. we don't count the parameters, as they're not
15241530
// part of the frame.
1525-
u32 value_stack_height = validator_.type_stack_size() + local_decl_count_;
1531+
u32 value_stack_height = validator_.type_stack_size() + local_count_;
15261532
CHECK_RESULT(validator_.OnTry(GetLocation(), sig_type));
15271533
// Push a label that tracks mapping of exn -> catch
15281534
PushLabel(LabelKind::Try, Istream::kInvalidOffset, Istream::kInvalidOffset,

test/interp/basic-logging.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ BeginModule(version: 1)
6262
OnFunctionBodyCount(1)
6363
BeginFunctionBody(0, size:5)
6464
OnLocalDeclCount(0)
65+
EndLocalDecls
6566
OnI32ConstExpr(42 (0x2a))
6667
OnReturnExpr
6768
OnEndExpr

test/regress/interp-ehv3-locals.txt

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
;;; NOTE: ref: issue-2476
44
(module
55
(tag $e0)
6-
(func (export "broken-local") (result i32)
6+
(func (export "set-local") (result i32)
77
(local $value i32)
88
(try $try
99
(do
@@ -14,9 +14,21 @@
1414
)
1515
(local.get $value)
1616
)
17+
(func (export "multiple-locals") (result i32)
18+
(local $a i32)
19+
(local $b i32)
20+
(try $try
21+
(do
22+
(throw $e0)
23+
)
24+
(catch $e0)
25+
)
26+
(local.get $a)
27+
)
1728
)
1829

19-
(assert_return (invoke "broken-local") (i32.const 1))
30+
(assert_return (invoke "set-local") (i32.const 1))
31+
(assert_return (invoke "multiple-locals") (i32.const 0))
2032
(;; STDOUT ;;;
21-
2/2 tests passed.
33+
3/3 tests passed.
2234
;;; STDOUT ;;)

0 commit comments

Comments
 (0)