mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 22:58:18 +00:00
feat(c-api) Handle initialized but empty results in wasm_func_call.
Our implementation of `wasm_func_call` was correct for C code as follows: ```c wasm_val_vec_t arguments = WASM_EMPTY_VEC; wasm_val_vec_t results = WASM_EMPTY_VEC; wasm_func_call(func, &arguments, &results); ``` However, for a C code such as: ```c wasm_val_t vals[1]; wasm_val_vec_t arguments = WASM_EMPTY_VEC; wasm_val_vec_t results = WASM_ARRAY_VEC(vals); wasm_func_call(func, &arguments, &results); ``` the `vals` array were kept empty/unchanged. Why? Because `wasm_func_call` was replacing the value of `results` by a new `wasm_val_vec_t`. It is correct when `results` is an empty vector, but it is incorrect when `results` is initialized with empty values. This patch tries to detect this pattern: If `results.data` is `null`, it means the vector is empty/uninitialized, and we can set a new `wasm_val_vec_t`, otherwise it means the vector is initialized with empty values, and we need to update each item individually.
This commit is contained in:
24
lib/c-api/src/wasm_c_api/externals/function.rs
vendored
24
lib/c-api/src/wasm_c_api/externals/function.rs
vendored
@@ -154,18 +154,34 @@ pub unsafe extern "C" fn wasm_func_call(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(TryInto::try_into)
|
.map(TryInto::try_into)
|
||||||
.collect::<Result<Vec<Val>, _>>()
|
.collect::<Result<Vec<Val>, _>>()
|
||||||
.expect("Argument conversion failed")
|
.expect("Arguments conversion failed")
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
match func.inner.call(¶ms) {
|
match func.inner.call(¶ms) {
|
||||||
Ok(wasm_results) => {
|
Ok(wasm_results) => {
|
||||||
*results = wasm_results
|
let vals = wasm_results
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(TryInto::try_into)
|
.map(TryInto::try_into)
|
||||||
.collect::<Result<Vec<wasm_val_t>, _>>()
|
.collect::<Result<Vec<wasm_val_t>, _>>()
|
||||||
.expect("Argument conversion failed")
|
.expect("Results conversion failed");
|
||||||
.into();
|
|
||||||
|
// `results` is an uninitialized vector. Set a new value.
|
||||||
|
if results.size == 0 || results.data.is_null() {
|
||||||
|
*results = vals.into();
|
||||||
|
}
|
||||||
|
// `results` is an initialized but empty vector. Fill it
|
||||||
|
// item per item.
|
||||||
|
else {
|
||||||
|
let slice = results
|
||||||
|
.into_slice_mut()
|
||||||
|
.expect("`wasm_func_call`, results' size is greater than 0 but data is NULL");
|
||||||
|
|
||||||
|
for (result, value) in slice.iter_mut().zip(vals.iter()) {
|
||||||
|
(*result).kind = value.kind;
|
||||||
|
(*result).of = value.of;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user