Closed
Description
opened on May 18, 2020
When code is compiled using the X87 FPU, comparing to infinity can lead to unexpected behavior.
I tried this code:
#[inline(never)]
fn get_num() -> f64 {
let num: f64 = 1.0e300;
// volatile is to avoid optimizations
unsafe { std::ptr::read_volatile(&num) }
}
fn main() {
let x = get_num();
let y = get_num();
let z = x * y;
if z != f64::INFINITY && z != f64::NEG_INFINITY && !z.is_nan() {
let exp = (z.to_bits() >> 52) & 0x7FF;
assert!(exp != 0x7FF);
println!("is finite, exp = {}", exp);
} else {
println!("is not finite");
}
}
I expected to see this happen:
This should either print "infinite or nan" or "is finite, exp = ...". The assert!
should never fail because the exponent bits are 0x7FF if and only if the number is infinity or nan, so the if
condition should have been false.
Instead, this happened:
When compiled for X86 without SSE, the assert will fail. This could also cause safety issues if unsafe
code relies on it.
The following command can be used to compile without SSE:
RUSTFLAGS="-C target-cpu=pentium" cargo run --target i686-unknown-linux-gnu
Meta
rustc --version --verbose
:
rustc 1.43.1 (8d69840ab 2020-05-04)
binary: rustc
commit-hash: 8d69840ab92ea7f4d323420088dd8c9775f180cd
commit-date: 2020-05-04
host: x86_64-unknown-linux-gnu
release: 1.43.1
LLVM version: 9.0
and
rustc 1.45.0-nightly (a74d1862d 2020-05-14)
binary: rustc
commit-hash: a74d1862d4d87a56244958416fd05976c58ca1a8
commit-date: 2020-05-14
host: x86_64-unknown-linux-gnu
release: 1.45.0-nightly
LLVM version: 9.0
Metadata
Assignees
Labels
Area: Code generationArea: Floating point numbers and arithmeticArea: Enabling/disabling target features like AVX, Neon, etc.Category: This is a bug.Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessTarget: x86 processors, 32 bit (like i686-*)Medium priorityRelevant to the compiler team, which will review and decide on the PR/issue.
Activity