Files
wasmtime/tests/all/table.rs
Alex Crichton 33312c5380 Fix a possible panic with null-containing element segments (#4455)
This commit fixes an issue with the initialization of element segments
when one of the elements in the element segment is `ref.func null`.
Previously the contents of a table were accidentally initialized with
the raw value of the `*mut VMCallerCheckedAnyfunc` which bypassed the
"this is initialized" encoding of function table entries that Wasmtime
uses for lazy table initialization. The fix here was to ensure that the
encoded form is used.

The impact of this issue is that a module could panic at runtime when
accessing a table element that was initialized with an element segment
containing a `ref.null func` entry. This only happens with imported
tables in a WebAssembly module where the table itself was defined on the
host. If the table was defined in another wasm module or in the local
wasm module this bug would not occur. Additionally this bug requires
enabling the reference types proposal for WebAssembly (which is enabled
by default) due to the usage of encodings for null funcrefs in element
segments.
2022-07-15 20:14:53 +00:00

78 lines
2.2 KiB
Rust

use anyhow::Result;
use wasmtime::*;
#[test]
fn get_none() {
let mut store = Store::<()>::default();
let ty = TableType::new(ValType::FuncRef, 1, None);
let table = Table::new(&mut store, ty, Val::FuncRef(None)).unwrap();
match table.get(&mut store, 0) {
Some(Val::FuncRef(None)) => {}
_ => panic!(),
}
assert!(table.get(&mut store, 1).is_none());
}
#[test]
fn fill_wrong() {
let mut store = Store::<()>::default();
let ty = TableType::new(ValType::FuncRef, 1, None);
let table = Table::new(&mut store, ty, Val::FuncRef(None)).unwrap();
assert_eq!(
table
.fill(&mut store, 0, Val::ExternRef(None), 1)
.map_err(|e| e.to_string())
.unwrap_err(),
"value does not match table element type"
);
let ty = TableType::new(ValType::ExternRef, 1, None);
let table = Table::new(&mut store, ty, Val::ExternRef(None)).unwrap();
assert_eq!(
table
.fill(&mut store, 0, Val::FuncRef(None), 1)
.map_err(|e| e.to_string())
.unwrap_err(),
"value does not match table element type"
);
}
#[test]
fn copy_wrong() {
let mut store = Store::<()>::default();
let ty = TableType::new(ValType::FuncRef, 1, None);
let table1 = Table::new(&mut store, ty, Val::FuncRef(None)).unwrap();
let ty = TableType::new(ValType::ExternRef, 1, None);
let table2 = Table::new(&mut store, ty, Val::ExternRef(None)).unwrap();
assert_eq!(
Table::copy(&mut store, &table1, 0, &table2, 0, 1)
.map_err(|e| e.to_string())
.unwrap_err(),
"tables do not have the same element type"
);
}
#[test]
fn null_elem_segment_works_with_imported_table() -> Result<()> {
let mut store = Store::<()>::default();
let ty = TableType::new(ValType::FuncRef, 1, None);
let table = Table::new(&mut store, ty, Val::FuncRef(None))?;
let module = Module::new(
store.engine(),
r#"
(module
(import "" "" (table (;0;) 1 funcref))
(func
i32.const 0
table.get 0
drop
)
(start 0)
(elem (;0;) (i32.const 0) funcref (ref.null func))
)
"#,
)?;
Instance::new(&mut store, &module, &[table.into()])?;
Ok(())
}