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:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user