about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-02-24 15:35:14 +0100
committerGitHub <noreply@github.com>2024-02-24 15:35:14 +0100
commitb87a713b9d0e94ec0d746fd22c7f869ceab0ee83 (patch)
treeeda03d6313d8cb565f1897d98f3928f460e5a585
parent3b827731d04e7d325ef31e16ed64bc88af72196b (diff)
parent134e2b2056d3d5519dc3b294ceb1558cf7af276c (diff)
downloadrust-b87a713b9d0e94ec0d746fd22c7f869ceab0ee83.tar.gz
rust-b87a713b9d0e94ec0d746fd22c7f869ceab0ee83.zip
Rollup merge of #121522 - RalfJung:insert-extract-boundscheck, r=oli-obk
check that simd_insert/extract indices are in-bounds

Fixes https://github.com/rust-lang/rust/issues/77477
r? `@oli-obk`
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs53
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl6
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs12
-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
-rw-r--r--tests/ui/simd/not-out-of-bounds.rs (renamed from tests/ui/simd/shuffle-not-out-of-bounds.rs)15
-rw-r--r--tests/ui/simd/not-out-of-bounds.stderr (renamed from tests/ui/simd/shuffle-not-out-of-bounds.stderr)42
9 files changed, 112 insertions, 69 deletions
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 23e6f054a7c..1eac2157cac 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1079,7 +1079,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             .map(|(arg_idx, val)| {
                 let idx = val.unwrap_leaf().try_to_i32().unwrap();
                 if idx >= i32::try_from(total_len).unwrap() {
-                    bx.sess().dcx().emit_err(InvalidMonomorphization::ShuffleIndexOutOfBounds {
+                    bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds {
                         span,
                         name,
                         arg_idx: arg_idx as u64,
@@ -1138,24 +1138,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 let val = bx.const_get_elt(vector, i as u64);
                 match bx.const_to_opt_u128(val, true) {
                     None => {
-                        bx.sess().dcx().emit_err(
-                            InvalidMonomorphization::ShuffleIndexNotConstant {
-                                span,
-                                name,
-                                arg_idx,
-                            },
-                        );
-                        None
+                        bug!("typeck should have already ensured that these are const")
                     }
                     Some(idx) if idx >= total_len => {
-                        bx.sess().dcx().emit_err(
-                            InvalidMonomorphization::ShuffleIndexOutOfBounds {
-                                span,
-                                name,
-                                arg_idx,
-                                total_len,
-                            },
-                        );
+                        bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds {
+                            span,
+                            name,
+                            arg_idx,
+                            total_len,
+                        });
                         None
                     }
                     Some(idx) => Some(bx.const_i32(idx as i32)),
@@ -1184,10 +1175,22 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
                 out_ty: arg_tys[2]
             }
         );
+        let idx = bx
+            .const_to_opt_u128(args[1].immediate(), false)
+            .expect("typeck should have ensure that this is a const");
+        if idx >= in_len.into() {
+            bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds {
+                span,
+                name,
+                arg_idx: 1,
+                total_len: in_len.into(),
+            });
+            return Ok(bx.const_null(llret_ty));
+        }
         return Ok(bx.insert_element(
             args[0].immediate(),
             args[2].immediate(),
-            args[1].immediate(),
+            bx.const_i32(idx as i32),
         ));
     }
     if name == sym::simd_extract {
@@ -1195,7 +1198,19 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
             ret_ty == in_elem,
             InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty }
         );
-        return Ok(bx.extract_element(args[0].immediate(), args[1].immediate()));
+        let idx = bx
+            .const_to_opt_u128(args[1].immediate(), false)
+            .expect("typeck should have ensure that this is a const");
+        if idx >= in_len.into() {
+            bx.sess().dcx().emit_err(InvalidMonomorphization::SimdIndexOutOfBounds {
+                span,
+                name,
+                arg_idx: 1,
+                total_len: in_len.into(),
+            });
+            return Ok(bx.const_null(llret_ty));
+        }
+        return Ok(bx.extract_element(args[0].immediate(), bx.const_i32(idx as i32)));
     }
 
     if name == sym::simd_select {
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index fa7719d8971..5ba66d1be43 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -106,14 +106,12 @@ codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `
 
 codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len}
 
-codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant
-
-codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len})
-
 codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}`
 
 codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}`
 
+codegen_ssa_invalid_monomorphization_simd_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: SIMD index #{$arg_idx} is out of bounds (limit {$total_len})
+
 codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}`
 
 codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}`
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index e42a8bd9ed9..a7ac502b248 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -797,16 +797,8 @@ pub enum InvalidMonomorphization<'tcx> {
         out_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = E0511)]
-    ShuffleIndexNotConstant {
-        #[primary_span]
-        span: Span,
-        name: Symbol,
-        arg_idx: u64,
-    },
-
-    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = E0511)]
-    ShuffleIndexOutOfBounds {
+    #[diag(codegen_ssa_invalid_monomorphization_simd_index_out_of_bounds, code = E0511)]
+    SimdIndexOutOfBounds {
         #[primary_span]
         span: Span,
         name: Symbol,
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
+
diff --git a/tests/ui/simd/shuffle-not-out-of-bounds.rs b/tests/ui/simd/not-out-of-bounds.rs
index 158e9956435..36d7a5865bc 100644
--- a/tests/ui/simd/shuffle-not-out-of-bounds.rs
+++ b/tests/ui/simd/not-out-of-bounds.rs
@@ -1,6 +1,6 @@
 //@ build-fail
 #![allow(non_camel_case_types)]
-#![feature(repr_simd, platform_intrinsics)]
+#![feature(repr_simd, core_intrinsics)]
 
 // Test for #73542 to verify out-of-bounds shuffle vectors do not compile.
 
@@ -28,9 +28,7 @@ struct u8x32([u8; 32]);
 #[derive(Copy, Clone)]
 struct u8x64([u8; 64]);
 
-extern "platform-intrinsic" {
-    pub fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
-}
+use std::intrinsics::simd::*;
 
 // Test vectors by lane size. Since LLVM does not distinguish between a shuffle
 // over two f32s and a shuffle over two u64s, or any other such combination,
@@ -70,13 +68,16 @@ fn main() {
     test_shuffle_lanes!(32, u8x32, simd_shuffle);
     test_shuffle_lanes!(64, u8x64, simd_shuffle);
 
-    extern "platform-intrinsic" {
-        fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
-    }
     let v = u8x2([0, 0]);
     const I: [u32; 2] = [4, 4];
     unsafe {
         let _: u8x2 = simd_shuffle(v, v, I);
         //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
     }
+
+    // also check insert/extract
+    unsafe {
+        simd_insert(v, 2, 0); //~ ERROR invalid monomorphization of `simd_insert` intrinsic
+        let _val: u8 = simd_extract(v, 2); //~ ERROR invalid monomorphization of `simd_extract` intrinsic
+    }
 }
diff --git a/tests/ui/simd/shuffle-not-out-of-bounds.stderr b/tests/ui/simd/not-out-of-bounds.stderr
index 59e5ab85866..5682935c1f1 100644
--- a/tests/ui/simd/shuffle-not-out-of-bounds.stderr
+++ b/tests/ui/simd/not-out-of-bounds.stderr
@@ -1,5 +1,5 @@
-error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4)
-  --> $DIR/shuffle-not-out-of-bounds.rs:51:21
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 4)
+  --> $DIR/not-out-of-bounds.rs:49:21
    |
 LL |                     $y(vec1, vec2, ARR)
    |                     ^^^^^^^^^^^^^^^^^^^
@@ -9,8 +9,8 @@ LL |     test_shuffle_lanes!(2, u8x2, simd_shuffle);
    |
    = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 8)
-  --> $DIR/shuffle-not-out-of-bounds.rs:51:21
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 8)
+  --> $DIR/not-out-of-bounds.rs:49:21
    |
 LL |                     $y(vec1, vec2, ARR)
    |                     ^^^^^^^^^^^^^^^^^^^
@@ -20,8 +20,8 @@ LL |     test_shuffle_lanes!(4, u8x4, simd_shuffle);
    |
    = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 16)
-  --> $DIR/shuffle-not-out-of-bounds.rs:51:21
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 16)
+  --> $DIR/not-out-of-bounds.rs:49:21
    |
 LL |                     $y(vec1, vec2, ARR)
    |                     ^^^^^^^^^^^^^^^^^^^
@@ -31,8 +31,8 @@ LL |     test_shuffle_lanes!(8, u8x8, simd_shuffle);
    |
    = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 32)
-  --> $DIR/shuffle-not-out-of-bounds.rs:51:21
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 32)
+  --> $DIR/not-out-of-bounds.rs:49:21
    |
 LL |                     $y(vec1, vec2, ARR)
    |                     ^^^^^^^^^^^^^^^^^^^
@@ -42,8 +42,8 @@ LL |     test_shuffle_lanes!(16, u8x16, simd_shuffle);
    |
    = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 64)
-  --> $DIR/shuffle-not-out-of-bounds.rs:51:21
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 64)
+  --> $DIR/not-out-of-bounds.rs:49:21
    |
 LL |                     $y(vec1, vec2, ARR)
    |                     ^^^^^^^^^^^^^^^^^^^
@@ -53,8 +53,8 @@ LL |     test_shuffle_lanes!(32, u8x32, simd_shuffle);
    |
    = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 128)
-  --> $DIR/shuffle-not-out-of-bounds.rs:51:21
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 128)
+  --> $DIR/not-out-of-bounds.rs:49:21
    |
 LL |                     $y(vec1, vec2, ARR)
    |                     ^^^^^^^^^^^^^^^^^^^
@@ -64,12 +64,24 @@ LL |     test_shuffle_lanes!(64, u8x64, simd_shuffle);
    |
    = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4)
-  --> $DIR/shuffle-not-out-of-bounds.rs:79:23
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 4)
+  --> $DIR/not-out-of-bounds.rs:74:23
    |
 LL |         let _: u8x2 = simd_shuffle(v, v, I);
    |                       ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `u8` (element of input `u8x2`), found `i32`
+  --> $DIR/not-out-of-bounds.rs:80:9
+   |
+LL |         simd_insert(v, 2, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_extract` intrinsic: SIMD index #1 is out of bounds (limit 2)
+  --> $DIR/not-out-of-bounds.rs:81:24
+   |
+LL |         let _val: u8 = simd_extract(v, 2);
+   |                        ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0511`.