Fix an off-by-two condition in heap legalization (#3462)
This commit fixes an issue in Cranelift where legalization of `heap_addr` instructions (used by wasm to represent heap accesses) could be off-by-two where loads that should be valid were actually treated as invalid. The bug here happened in an optimization where tests against odd constants were being altered to tests against even constants by subtracting one from the limit instead of adding one to the limit. The comment around this area has been updated in accordance with a little more math-stuff as well to help future readers.
This commit is contained in:
@@ -321,3 +321,40 @@ fn massive_64_bit_still_limited() -> Result<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tiny_static_heap() -> Result<()> {
|
||||
// The size of the memory in the module below is the exact same size as
|
||||
// the static memory size limit in the configuration. This is intended to
|
||||
// specifically test that a load of all the valid addresses of the memory
|
||||
// all pass bounds-checks in cranelift to help weed out any off-by-one bugs.
|
||||
let mut config = Config::new();
|
||||
config.static_memory_maximum_size(65536);
|
||||
let engine = Engine::new(&config)?;
|
||||
let mut store = Store::new(&engine, ());
|
||||
|
||||
let module = Module::new(
|
||||
&engine,
|
||||
r#"
|
||||
(module
|
||||
(memory 1 1)
|
||||
(func (export "run")
|
||||
(local $i i32)
|
||||
|
||||
(loop
|
||||
(if (i32.eq (local.get $i) (i32.const 65536))
|
||||
(return))
|
||||
(drop (i32.load8_u (local.get $i)))
|
||||
(local.set $i (i32.add (local.get $i) (i32.const 1)))
|
||||
br 0
|
||||
)
|
||||
)
|
||||
)
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let i = Instance::new(&mut store, &module, &[])?;
|
||||
let f = i.get_typed_func::<(), (), _>(&mut store, "run")?;
|
||||
f.call(&mut store, ())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user