about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-02-23 19:34:17 +0100
committerRalf Jung <post@ralfj.de>2024-02-23 19:43:59 +0100
commit134e2b2056d3d5519dc3b294ceb1558cf7af276c (patch)
tree58f132b16968b1df25cca80c23c145b2fea50630
parent8e0dd993d63d179402b0f5330aadfe589069b387 (diff)
downloadrust-134e2b2056d3d5519dc3b294ceb1558cf7af276c.tar.gz
rust-134e2b2056d3d5519dc3b294ceb1558cf7af276c.zip
interpret: do no ICE on OOB shuffle/insert/extract indices
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs20
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs10
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-extract.rs8
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-extract.stderr15
4 files changed, 39 insertions, 14 deletions
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index f020616f6d8..1cb991b38f7 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -379,10 +379,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let (input, input_len) = self.operand_to_simd(&args[0])?;
                 let (dest, dest_len) = self.place_to_simd(dest)?;
                 assert_eq!(input_len, dest_len, "Return vector length must match input length");
-                assert!(
-                    index < dest_len,
-                    "Index `{index}` must be in bounds of vector with length {dest_len}"
-                );
+                // Bounds are not checked by typeck so we have to do it ourselves.
+                if index >= input_len {
+                    throw_ub_format!(
+                        "`simd_insert` index {index} is out-of-bounds of vector with length {input_len}"
+                    );
+                }
 
                 for i in 0..dest_len {
                     let place = self.project_index(&dest, i)?;
@@ -397,10 +399,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             sym::simd_extract => {
                 let index = u64::from(self.read_scalar(&args[1])?.to_u32()?);
                 let (input, input_len) = self.operand_to_simd(&args[0])?;
-                assert!(
-                    index < input_len,
-                    "index `{index}` must be in bounds of vector with length {input_len}"
-                );
+                // Bounds are not checked by typeck so we have to do it ourselves.
+                if index >= input_len {
+                    throw_ub_format!(
+                        "`simd_extract` index {index} is out-of-bounds of vector with length {input_len}"
+                    );
+                }
                 self.copy_op(&self.project_index(&input, index)?, dest)?;
             }
             sym::likely | sym::unlikely | sym::black_box => {
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index ea2d104694a..ca8773cac14 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -563,9 +563,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         let right_idx = src_index.checked_sub(left_len).unwrap();
                         this.read_immediate(&this.project_index(&right, right_idx)?)?
                     } else {
-                        span_bug!(
-                            this.cur_span(),
-                            "simd_shuffle index {src_index} is out of bounds for 2 vectors of size {left_len}",
+                        throw_ub_format!(
+                            "`simd_shuffle_generic` index {src_index} is out-of-bounds for 2 vectors with length {dest_len}"
                         );
                     };
                     this.write_immediate(*val, &dest)?;
@@ -604,9 +603,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         let right_idx = src_index.checked_sub(left_len).unwrap();
                         this.read_immediate(&this.project_index(&right, right_idx)?)?
                     } else {
-                        span_bug!(
-                            this.cur_span(),
-                            "simd_shuffle index {src_index} is out of bounds for 2 vectors of size {left_len}",
+                        throw_ub_format!(
+                            "`simd_shuffle` index {src_index} is out-of-bounds for 2 vectors with length {dest_len}"
                         );
                     };
                     this.write_immediate(*val, &dest)?;
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-extract.rs b/src/tools/miri/tests/fail/intrinsics/simd-extract.rs
new file mode 100644
index 00000000000..02b9d30df5e
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/simd-extract.rs
@@ -0,0 +1,8 @@
+#![feature(portable_simd, core_intrinsics)]
+use std::simd::*;
+
+fn main() {
+    let v = i32x4::splat(0);
+    let _x: i32 = unsafe { std::intrinsics::simd::simd_extract(v, 4) };
+    //~^ERROR: index 4 is out-of-bounds
+}
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-extract.stderr b/src/tools/miri/tests/fail/intrinsics/simd-extract.stderr
new file mode 100644
index 00000000000..dc6b22de492
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/simd-extract.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: `simd_extract` index 4 is out-of-bounds of vector with length 4
+  --> $DIR/simd-extract.rs:LL:CC
+   |
+LL |     let _x: i32 = unsafe { std::intrinsics::simd::simd_extract(v, 4) };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_extract` index 4 is out-of-bounds of vector with length 4
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/simd-extract.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+