Skip to content

Commit f37d193

Browse files
committed
[stack-switching] Fix type index conflation in the translation of switch
The translation of `switch` would erroneously decompose a `ModuleInternedTypeIndex` and use its `u32` representation to build a `TypeIndex`. The two index types map different spaces, consequently it is possible to cause a compiler crash (out of bounds on lookup) or worse a runtime crash (argument types mismatch).
1 parent ac07729 commit f37d193

3 files changed

Lines changed: 46 additions & 2 deletions

File tree

crates/cranelift/src/func_environ.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5584,6 +5584,15 @@ impl FuncEnvironment<'_> {
55845584
)
55855585
}
55865586

5587+
pub fn continuation_arguments_from_interned(
5588+
&self,
5589+
index: ModuleInternedTypeIndex,
5590+
) -> &[WasmValType] {
5591+
self.types[self.types[index].unwrap_cont().unwrap_module_type_index()]
5592+
.unwrap_func()
5593+
.params()
5594+
}
5595+
55875596
pub fn continuation_arguments(&self, index: TypeIndex) -> &[WasmValType] {
55885597
let idx = self.module.types[index].unwrap_module_type_index();
55895598
self.types[self.types[idx].unwrap_cont().unwrap_module_type_index()]

crates/cranelift/src/translate/code_translator.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3335,10 +3335,10 @@ pub fn translate_operator(
33353335
WasmHeapType::ConcreteCont(index) => {
33363336
let mti = index
33373337
.as_module_type_index()
3338-
.expect("Only supporting module type indices on switch for now");
3338+
.expect("expected module-local type index");
33393339

33403340
environ
3341-
.continuation_arguments(TypeIndex::from_u32(mti.as_u32()))
3341+
.continuation_arguments_from_interned(mti)
33423342
.iter()
33433343
.map(|ty| crate::value_type(environ.isa(), *ty))
33443344
.collect()
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
;;! bulk_memory = true
2+
;;! function_references = true
3+
;;! stack_switching = true
4+
5+
;; Regression test for buggy module-local type index to declared type
6+
;; index conversion.
7+
(module
8+
;; These two function types canonicalize to the same module-interned type.
9+
;; As a result, subsequent TypeIndex and ModuleInternedTypeIndex values do
10+
;; not have the same numeric value.
11+
(type $duplicate (func))
12+
(type $ft0 (func))
13+
14+
(type $ct0 (cont $ft0))
15+
16+
(type $ft1 (func (param (ref $ct0))))
17+
(type $ct1 (cont $ft1))
18+
19+
(tag $t)
20+
21+
(func $f
22+
(cont.new $ct1 (ref.func $g))
23+
(switch $ct1 $t))
24+
(elem declare func $f)
25+
26+
(func $g (type $ft1))
27+
(elem declare func $g)
28+
29+
(func (export "entry") (result i32)
30+
(cont.new $ct0 (ref.func $f))
31+
(resume $ct0 (on $t switch))
32+
(i32.const 0))
33+
)
34+
35+
(assert_return (invoke "entry") (i32.const 0))

0 commit comments

Comments
 (0)