Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions crates/wasmparser/src/validator/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1911,10 +1911,21 @@ where
}
Handle::OnSwitch { tag } => {
let tag_ty = self.tag_at(tag)?;
if !self.is_func_subtype(
// The tag's type must be *equivalent* to (not merely a
// subtype of) `[] -> [old results]`: the handler judgment
// has no subsumption rule, so `(on tu switch) : t*` together
// with the required `hdl : t2*` forces `t* = t2*`. Checking
// subtyping in both directions gives equivalence, and also
// pins the tag to zero parameters (via the param-length
// check inside `is_func_subtype`).
let tag_matches = self.is_func_subtype(
(tag_ty.params(), tag_ty.results()),
(&[], old_func_ty.results()),
) {
) && self.is_func_subtype(
(&[], old_func_ty.results()),
(tag_ty.params(), tag_ty.results()),
);
if !tag_matches {
bail!(
self.offset,
"type mismatch: switch tag does not match continuation"
Expand Down
23 changes: 22 additions & 1 deletion tests/cli/stack-switching/validate-switch-label.wast
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,32 @@
)
"type mismatch: switch tag does not match continuation")

;; The switch tag's results must be *equivalent* to the continuation's results,
;; not merely a subtype. Here the tag results `[nullfuncref]` are a strict
;; subtype of the continuation results `[funcref]`, so this must be rejected.
(assert_invalid
(module
(type $ft (func (result funcref)))
(type $ct (cont $ft))

(type $tag_ft (func (result nullfuncref)))
(tag $t (type $tag_ft))

(func
block $label
(resume $ct (on $t switch) (ref.null $ct))
unreachable
end
)
)
"type mismatch: switch tag does not match continuation")

;; Equivalent reference-type results (both `[funcref]`) are accepted.
(module
(type $ft (func (result funcref)))
(type $ct (cont $ft))

(type $tag_ft (func (result nullfuncref)))
(type $tag_ft (func (result funcref)))
(tag $t (type $tag_ft))

(func
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,16 @@
"text": "type mismatch: switch tag does not match continuation"
},
{
"type": "module",
"line": 86,
"type": "assert_invalid",
"line": 90,
"filename": "validate-switch-label.5.wasm",
"module_type": "binary",
"text": "type mismatch: switch tag does not match continuation"
},
{
"type": "module",
"line": 107,
"filename": "validate-switch-label.6.wasm",
"module_type": "binary"
}
]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
(module
(type $ft (;0;) (func (result funcref)))
(type $ct (;1;) (cont $ft))
(type $tag_ft (;2;) (func (result nullfuncref)))
(type $tag_ft (;2;) (func (result funcref)))
(type (;3;) (func))
(tag $t (;0;) (type $tag_ft) (result nullfuncref))
(tag $t (;0;) (type $tag_ft) (result funcref))
(func (;0;) (type 3)
block $label
ref.null $ct
Expand Down
Loading