I just would like to know what is going on and if this could maybe be a compiler bug. The problem is actually very easy to circumvent, as it is quite specific...
Just in case this is an OSI layer 8 problem - apologies upfront!
My Cargo.toml looks like this:
[package]
name = "asan_lto_reproducer"
version = "0.1.0"
edition = "2021"
[profile.release]
panic = "abort"
[dependencies]
lib.rs:
#[cfg(test)]
mod tests {
fn foo(_s: &str) {}
#[test]
#[should_panic]
fn weird() {
let some_string = String::from("some_string");
// std::hint::black_box(foo(&some_string)); // comment this in for great success!
panic!("blarb");
}
}
Command:
export RUSTFLAGS="\
-Zsanitizer=address \
-Clto=no \
"
cargo \
+nightly \
test \
-Zpanic-abort-tests \
--release
With this setup and the given command, the test fails with:
running 1 test
test tests::weird - should panic ... FAILED
failures:
---- tests::weird stdout ----
---- tests::weird stderr ----
thread 'main' panicked at src/lib.rs:10:9:
blarb
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
=================================================================
==71672==ERROR: LeakSanitizer: detected memory leaks
<ASAN output>
If I change any of these settings, the test succeeds:
- comment-toggle the black_box line
- remove ASAN flag
- remove disable LTO flag
- remove release flag
- remove the panic-abort-tests flag
- remove the panic=abort setting in Cargo.toml
As a sidenote, I also tried with additional flags for ASAN, but it did not change anything, so I left them out:
-Zbuild-std=std,panic_abort \
--target=x86_64-unknown-linux-gnu \
My expectation would be exactly the opposite of what is actually happening with the black_box line:
- When the String is not used, the compiler is optimizing it out, nothing leaks, and no error is reported.
- If it is used in the black box, it won't be optimized out, it leaks, causing the test to fail.
- Also, the test succeeds in debug mode, I would expect it to do the same in release.
BTW, I found a bug that might have something to do with it. It seems to be not deterministic, but has a lot of things in common (panic abort, LTO disabled, should_panic):
So I don't know what is happening, but my assumption is that somehting is going on with optimization. I played around a bit, but can't make any sense of it. Maybe somebody else has some insight? Should I file a bug?
Thanks in advance!