Description
Relevant comment on IRLO. The following code leads to illegal instruction
in release mode. (It works fine, printing 42
in debug mode.)
pub unsafe fn foo(x: *const i8) -> i8 {
*x.wrapping_sub(x as _).wrapping_add(x as _)
}
fn main() {
let x = 42;
println!("{}", unsafe {foo(&x)});
}
Apparently, leaving the object x
with a wrapping_sup
, then going back into the object with wrapping_add
and dereferencing the resulting pointer is supposed to be safe (although there is still an open issue (#80306) about properly documenting that this is safe).
As discussed in the linked IRLO thread, what’s probably happening here is that LLVM realizes that the first x.wrapping_sub(x as _)
evaluates to the null pointer, and then considers the code equivalent to something like *std::ptr::null().wrapping_add(x as _)
which is then detected as UB (dereferencing some integer offset of the null pointer), hence the illegal instruction.
Errors:
Compiling playground v0.0.1 (/playground)
Finished release [optimized] target(s) in 1.03s
Running `target/release/playground`
timeout: the monitored command dumped core
/playground/tools/entrypoint.sh: line 11: 7 Illegal instruction timeout --signal=KILL ${timeout} "$@"