Skip to content

Commit d72debf

Browse files
committed
require memory for async lifts as needed
Per WebAssembly/component-model#575, both `wasm-tools` and Wasmtime have been too permissive, allowing async lifts to optionally omit a memory canonopt if only the return type (and not the parameter types) would need one. This fixes validation to require the option in such cases. Signed-off-by: Joel Dice <[email protected]>
1 parent ec6b54a commit d72debf

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

crates/wasmparser/src/validator/component_types.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,21 @@ impl ComponentFuncType {
12751275
sig.results.assert_push(ValType::I32);
12761276
}
12771277
(Abi::Lift, Concurrency::Async { callback }) => {
1278+
if let Some(ty) = &self.result {
1279+
// The result of an async lift will be returned via a call
1280+
// to `task.return` rather than the lifted function itself.
1281+
// Here we require a memory if either the return type
1282+
// contains a pointer or has a flattened form that exceeds
1283+
// `MAX_FLAT_FUNC_PARAMS`.
1284+
//
1285+
// Note that the return type itself has no effect on the
1286+
// expected core signature of the lifted function.
1287+
1288+
let overflow =
1289+
!ty.push_wasm_types(types, &mut LoweredTypes::new(MAX_FLAT_FUNC_PARAMS));
1290+
1291+
options.require_memory_if(offset, || overflow || ty.contains_ptr(types))?;
1292+
}
12781293
if callback.is_some() {
12791294
sig.results.assert_push(ValType::I32);
12801295
}

tests/cli/component-model/async/lift.wast

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,35 @@
108108
)
109109
"cannot specify callback without async"
110110
)
111+
112+
;; async lift; missing memory (needed for string return value)
113+
(assert_invalid
114+
(component
115+
(core module $m
116+
(func (export "callback") (param i32 i32 i32) (result i32) unreachable)
117+
(func (export "foo") (result i32) unreachable)
118+
)
119+
(core instance $i (instantiate $m))
120+
121+
(func (export "foo") (result string)
122+
(canon lift (core func $i "foo") async (callback (func $i "callback")))
123+
)
124+
)
125+
"canonical option `memory` is required"
126+
)
127+
128+
;; async lift; missing memory (needed for return value exceeding MAX_FLAT_PARAMS)
129+
(assert_invalid
130+
(component
131+
(core module $m
132+
(func (export "callback") (param i32 i32 i32) (result i32) unreachable)
133+
(func (export "foo") (result i32) unreachable)
134+
)
135+
(core instance $i (instantiate $m))
136+
137+
(func (export "foo") (result (tuple u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32 u32))
138+
(canon lift (core func $i "foo") async (callback (func $i "callback")))
139+
)
140+
)
141+
"canonical option `memory` is required"
142+
)

tests/snapshots/cli/component-model/async/lift.wast.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@
4848
"filename": "lift.6.wasm",
4949
"module_type": "binary",
5050
"text": "cannot specify callback without async"
51+
},
52+
{
53+
"type": "assert_invalid",
54+
"line": 114,
55+
"filename": "lift.7.wasm",
56+
"module_type": "binary",
57+
"text": "canonical option `memory` is required"
58+
},
59+
{
60+
"type": "assert_invalid",
61+
"line": 130,
62+
"filename": "lift.8.wasm",
63+
"module_type": "binary",
64+
"text": "canonical option `memory` is required"
5165
}
5266
]
5367
}

0 commit comments

Comments
 (0)