From e591b83185ba60cec09225d5ed6b41325a7a331f Mon Sep 17 00:00:00 2001 From: Smitty Date: Sun, 2 May 2021 12:25:00 -0400 Subject: [PATCH] UB if f*_fast intrinsic called with nonfinite value --- src/shims/intrinsics.rs | 30 ++++++++++++++++++++++++++ tests/compile-fail/fast_math_both.rs | 7 ++++++ tests/compile-fail/fast_math_first.rs | 7 ++++++ tests/compile-fail/fast_math_second.rs | 7 ++++++ 4 files changed, 51 insertions(+) create mode 100644 tests/compile-fail/fast_math_both.rs create mode 100644 tests/compile-fail/fast_math_first.rs create mode 100644 tests/compile-fail/fast_math_second.rs diff --git a/src/shims/intrinsics.rs b/src/shims/intrinsics.rs index 64c6e0a540f..cae9c813c17 100644 --- a/src/shims/intrinsics.rs +++ b/src/shims/intrinsics.rs @@ -173,6 +173,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx "frem_fast" => mir::BinOp::Rem, _ => bug!(), }; + let a_valid = match a.layout.ty.kind() { + ty::Float(FloatTy::F32) => a.to_scalar()?.to_f32()?.is_finite(), + ty::Float(FloatTy::F64) => a.to_scalar()?.to_f64()?.is_finite(), + _ => bug!( + "`{}` called with non-float input type {:?}", + intrinsic_name, + a.layout.ty + ), + }; + if !a_valid { + throw_ub_format!( + "`{}` intrinsic called with non-finite value as first parameter", + intrinsic_name, + ); + } + let b_valid = match b.layout.ty.kind() { + ty::Float(FloatTy::F32) => b.to_scalar()?.to_f32()?.is_finite(), + ty::Float(FloatTy::F64) => b.to_scalar()?.to_f64()?.is_finite(), + _ => bug!( + "`{}` called with non-float input type {:?}", + intrinsic_name, + b.layout.ty + ), + }; + if !b_valid { + throw_ub_format!( + "`{}` intrinsic called with non-finite value as second parameter", + intrinsic_name, + ); + } this.binop_ignore_overflow(op, &a, &b, dest)?; } diff --git a/tests/compile-fail/fast_math_both.rs b/tests/compile-fail/fast_math_both.rs new file mode 100644 index 00000000000..470ebe62005 --- /dev/null +++ b/tests/compile-fail/fast_math_both.rs @@ -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 + } +} diff --git a/tests/compile-fail/fast_math_first.rs b/tests/compile-fail/fast_math_first.rs new file mode 100644 index 00000000000..184476a4741 --- /dev/null +++ b/tests/compile-fail/fast_math_first.rs @@ -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 first parameter + } +} diff --git a/tests/compile-fail/fast_math_second.rs b/tests/compile-fail/fast_math_second.rs new file mode 100644 index 00000000000..114197d7579 --- /dev/null +++ b/tests/compile-fail/fast_math_second.rs @@ -0,0 +1,7 @@ +#![feature(core_intrinsics)] + +fn main() { + unsafe { + let _x: f32 = core::intrinsics::fmul_fast(3.4f32, f32::NAN); //~ ERROR `fmul_fast` intrinsic called with non-finite value as second parameter + } +}