Account for fuel before unconditionally trapping Wasm accesses (#5447)

* Account for fuel before unconditionally trapping Wasm accesses

Fixes #5445

* Add a test for fuel accounting and unconditionally trapping memory accesses
This commit is contained in:
Nick Fitzgerald
2022-12-15 12:18:52 -08:00
committed by GitHub
parent 0a6a28a4fb
commit 1fe56d7efb
5 changed files with 80 additions and 15 deletions

View File

@@ -183,3 +183,43 @@ fn manual_edge_cases() {
assert!(store.consume_fuel(i64::MAX as u64 + 1).is_err());
assert_eq!(store.consume_fuel(i64::MAX as u64).unwrap(), 0);
}
#[test]
fn unconditionally_trapping_memory_accesses_save_fuel_before_trapping() {
let mut config = Config::new();
config.consume_fuel(true);
config.static_memory_maximum_size(0x1_0000);
let engine = Engine::new(&config).unwrap();
let module = Module::new(
&engine,
r#"
(module
(memory 1 1)
(func (export "f") (param i32) (result i32)
local.get 0
local.get 0
i32.add
;; This offset is larger than our memory max size and therefore
;; will unconditionally trap.
i32.load8_s offset=0xffffffff))
"#,
)
.unwrap();
let mut store = Store::new(&engine, ());
store.add_fuel(1_000).unwrap();
let instance = Instance::new(&mut store, &module, &[]).unwrap();
let f = instance
.get_typed_func::<i32, i32>(&mut store, "f")
.unwrap();
let trap = f.call(&mut store, 0).unwrap_err();
assert_eq!(trap.downcast::<Trap>().unwrap(), Trap::MemoryOutOfBounds);
// The `i32.add` consumed some fuel before the unconditionally trapping
// memory access.
assert!(store.fuel_consumed().unwrap() > 0);
}