| 129 | #[tokio::test] |
| 130 | #[cfg_attr(asan, ignore)] |
| 131 | async fn called_on_custom_heap_stack() -> Result<()> { |
| 132 | let (mut store, stack_creator) = config(); |
| 133 | let module = Module::new( |
| 134 | store.engine(), |
| 135 | r#" |
| 136 | (module |
| 137 | (import "host" "callback" (func $callback (result i64))) |
| 138 | (func $f (result i64) (call $callback)) |
| 139 | (export "f" (func $f)) |
| 140 | ) |
| 141 | "#, |
| 142 | )?; |
| 143 | |
| 144 | let ty = FuncType::new(store.engine(), [], [ValType::I64]); |
| 145 | let host_func = Func::new(&mut store, ty, move |_caller, _params, results| { |
| 146 | let foo = 42; |
| 147 | // output an address on the stack |
| 148 | results[0] = Val::I64((&foo as *const i32) as usize as i64); |
| 149 | Ok(()) |
| 150 | }); |
| 151 | let export = wasmtime::Extern::Func(host_func); |
| 152 | let instance = Instance::new_async(&mut store, &module, &[export]).await?; |
| 153 | let mut results = [Val::I64(0)]; |
| 154 | instance |
| 155 | .get_func(&mut store, "f") |
| 156 | .context("missing function export")? |
| 157 | .call_async(&mut store, &[], &mut results) |
| 158 | .await?; |
| 159 | // Make sure the stack address we wrote was within our custom stack range |
| 160 | let stack_address = results[0].i64().unwrap() as usize; |
| 161 | assert!(stack_creator.range().contains(&stack_address)); |
| 162 | Ok(()) |
| 163 | } |