From e591b83185ba60cec09225d5ed6b41325a7a331f Mon Sep 17 00:00:00 2001 From: Smitty Date: Sun, 2 May 2021 12:25:00 -0400 Subject: [PATCH 1/3] 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 64c6e0a540f8..cae9c813c179 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 000000000000..470ebe620050 --- /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 000000000000..184476a47417 --- /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 000000000000..114197d75793 --- /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 + } +} From 68d29554a8bf100d1a6c95eefb4cd258b4fd1605 Mon Sep 17 00:00:00 2001 From: Smitty Date: Mon, 3 May 2021 09:56:51 -0400 Subject: [PATCH 2/3] test for infinite value in f*_fast --- tests/compile-fail/fast_math_second.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/compile-fail/fast_math_second.rs b/tests/compile-fail/fast_math_second.rs index 114197d75793..e8d70a4a79e7 100644 --- a/tests/compile-fail/fast_math_second.rs +++ b/tests/compile-fail/fast_math_second.rs @@ -2,6 +2,6 @@ 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 + let _x: f32 = core::intrinsics::fmul_fast(3.4f32, f32::INFINITY); //~ ERROR `fmul_fast` intrinsic called with non-finite value as second parameter } } From e0e59f60205f08486225d0703e666c5cf896fd21 Mon Sep 17 00:00:00 2001 From: Smitty Date: Mon, 3 May 2021 10:08:42 -0400 Subject: [PATCH 3/3] Simplify finiteness checking --- src/shims/intrinsics.rs | 42 ++++++++++++--------------- tests/compile-fail/fast_math_both.rs | 2 +- tests/compile-fail/fast_math_first.rs | 2 +- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/shims/intrinsics.rs b/src/shims/intrinsics.rs index cae9c813c179..b33b9666f712 100644 --- a/src/shims/intrinsics.rs +++ b/src/shims/intrinsics.rs @@ -173,35 +173,31 @@ 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 - ), + 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 + ), + }) }; - if !a_valid { - throw_ub_format!( + 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, - ); - } - 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!( + (_, false) => 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 index 470ebe620050..844e4e95211f 100644 --- a/tests/compile-fail/fast_math_both.rs +++ b/tests/compile-fail/fast_math_both.rs @@ -2,6 +2,6 @@ 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 + let _x: f32 = core::intrinsics::fsub_fast(f32::NAN, f32::NAN); //~ ERROR `fsub_fast` intrinsic called with non-finite value as both parameters } } diff --git a/tests/compile-fail/fast_math_first.rs b/tests/compile-fail/fast_math_first.rs index 184476a47417..470ebe620050 100644 --- a/tests/compile-fail/fast_math_first.rs +++ b/tests/compile-fail/fast_math_first.rs @@ -2,6 +2,6 @@ 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 + let _x: f32 = core::intrinsics::frem_fast(f32::NAN, 3.2); //~ ERROR `frem_fast` intrinsic called with non-finite value as first parameter } }