Auto merge of #1785 - Smittyvb:fast-math-ub, r=RalfJung

Throw UB if f*_fast intrinsic called with non-finite value

Calling these intrinsics with non-finite values is undefined behaviour, since they result in `f*` intrinsics in LLVM with the `fast` flag, and `fast` math on non-finite values results in `poison` values. (technically LLVM only considers it UB upon _using_ the value, but that shouldn't make much of a difference)
This commit is contained in:
bors 2021-05-03 17:32:50 +00:00
commit bdce1ddf88
4 changed files with 47 additions and 0 deletions

View File

@ -173,6 +173,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
"frem_fast" => mir::BinOp::Rem,
_ => bug!(),
};
let float_finite = |x: ImmTy<'tcx, _>| -> InterpResult<'tcx, bool> {
Ok(match x.layout.ty.kind() {
ty::Float(FloatTy::F32) => x.to_scalar()?.to_f32()?.is_finite(),
ty::Float(FloatTy::F64) => x.to_scalar()?.to_f64()?.is_finite(),
_ => bug!(
"`{}` called with non-float input type {:?}",
intrinsic_name,
x.layout.ty
),
})
};
match (float_finite(a)?, float_finite(b)?) {
(false, false) => throw_ub_format!(
"`{}` intrinsic called with non-finite value as both parameters",
intrinsic_name,
),
(false, _) => throw_ub_format!(
"`{}` intrinsic called with non-finite value as first parameter",
intrinsic_name,
),
(_, false) => throw_ub_format!(
"`{}` intrinsic called with non-finite value as second parameter",
intrinsic_name,
),
_ => {}
}
this.binop_ignore_overflow(op, &a, &b, dest)?;
}

View File

@ -0,0 +1,7 @@
#![feature(core_intrinsics)]
fn main() {
unsafe {
let _x: f32 = core::intrinsics::fsub_fast(f32::NAN, f32::NAN); //~ ERROR `fsub_fast` intrinsic called with non-finite value as both parameters
}
}

View File

@ -0,0 +1,7 @@
#![feature(core_intrinsics)]
fn main() {
unsafe {
let _x: f32 = core::intrinsics::frem_fast(f32::NAN, 3.2); //~ ERROR `frem_fast` intrinsic called with non-finite value as first parameter
}
}

View File

@ -0,0 +1,7 @@
#![feature(core_intrinsics)]
fn main() {
unsafe {
let _x: f32 = core::intrinsics::fmul_fast(3.4f32, f32::INFINITY); //~ ERROR `fmul_fast` intrinsic called with non-finite value as second parameter
}
}