Skip to content

Commit 7813436

Browse files
authored
Fix panic with out-of-bounds flags in Value (bytecodealliance#13015)
This commit fixes a panic when a component model `Value` is lifted from a flags value which specifies out-of-bounds bits as 1. This is specified in the component model to ignore the out-of-bounds bits, which `flags!` correctly did (and thus `bindgen!`), but `Value` treated out-of-bounds bits as a panic due to indexing an array.
1 parent 1845118 commit 7813436

2 files changed

Lines changed: 70 additions & 1 deletion

File tree

crates/wasmtime/src/runtime/component/values.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,7 @@ fn lower_map<T>(
11421142
}
11431143

11441144
fn push_flags(ty: &TypeFlags, flags: &mut Vec<String>, mut offset: u32, mut bits: u32) {
1145-
while bits > 0 {
1145+
while bits > 0 && usize::try_from(offset).unwrap() < ty.names.len() {
11461146
if bits & 1 != 0 {
11471147
flags.push(ty.names[offset as usize].clone());
11481148
}

tests/all/component_model/dynamic.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,3 +1237,72 @@ fn introspection() -> Result<()> {
12371237
);
12381238
Ok(())
12391239
}
1240+
1241+
#[test]
1242+
fn flags_beyond_end() -> Result<()> {
1243+
let engine = super::engine();
1244+
1245+
let component = Component::new(
1246+
&engine,
1247+
r#"
1248+
(component
1249+
(type $f' (flags "a" "b"))
1250+
(export $f "f" (type $f'))
1251+
1252+
(core module $m
1253+
(func (export "r") (param i32) (result i32) local.get 0)
1254+
)
1255+
(core instance $i (instantiate $m))
1256+
(func (export "run") (param "x" u32) (result $f)
1257+
(canon lift (core func $i "r")))
1258+
)
1259+
"#,
1260+
)?;
1261+
let mut store = Store::new(&engine, ());
1262+
let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
1263+
let run = instance.get_func(&mut store, "run").unwrap();
1264+
1265+
let mut output = [Val::Bool(false)];
1266+
run.call(&mut store, &[Val::U32(0)], &mut output)?;
1267+
assert_eq!(output[0], Val::Flags(vec![]));
1268+
1269+
let mut output = [Val::Bool(false)];
1270+
run.call(&mut store, &[Val::U32(1)], &mut output)?;
1271+
assert_eq!(output[0], Val::Flags(vec!["a".to_string()]));
1272+
1273+
let mut output = [Val::Bool(false)];
1274+
run.call(&mut store, &[Val::U32(2)], &mut output)?;
1275+
assert_eq!(output[0], Val::Flags(vec!["b".to_string()]));
1276+
1277+
let mut output = [Val::Bool(false)];
1278+
run.call(&mut store, &[Val::U32(3)], &mut output)?;
1279+
assert_eq!(
1280+
output[0],
1281+
Val::Flags(vec!["a".to_string(), "b".to_string()])
1282+
);
1283+
let mut output = [Val::Bool(false)];
1284+
1285+
run.call(&mut store, &[Val::U32(4)], &mut output)?;
1286+
assert_eq!(output[0], Val::Flags(vec![]));
1287+
1288+
run.call(&mut store, &[Val::U32(5)], &mut output)?;
1289+
assert_eq!(output[0], Val::Flags(vec!["a".to_string()]));
1290+
1291+
wasmtime::component::flags! {
1292+
F {
1293+
#[component(name = "a")]
1294+
const A;
1295+
#[component(name = "b")]
1296+
const B;
1297+
}
1298+
}
1299+
1300+
let run = instance.get_typed_func::<(u32,), (F,)>(&mut store, "run")?;
1301+
assert_eq!(run.call(&mut store, (0,))?, (F::empty(),));
1302+
assert_eq!(run.call(&mut store, (1,))?, (F::A,));
1303+
assert_eq!(run.call(&mut store, (2,))?, (F::B,));
1304+
assert_eq!(run.call(&mut store, (3,))?, (F::A | F::B,));
1305+
assert_eq!(run.call(&mut store, (4,))?, (F::empty(),));
1306+
assert_eq!(run.call(&mut store, (5,))?, (F::A,));
1307+
Ok(())
1308+
}

0 commit comments

Comments
 (0)