Skip to content

Commit

Permalink
Auto merge of #121522 - RalfJung:insert-extract-boundscheck, r=oli-obk
Browse files Browse the repository at this point in the history
check that simd_insert/extract indices are in-bounds

Fixes #77477
r? `@oli-obk`
  • Loading branch information
bors committed Feb 23, 2024
2 parents 8f359be + 134e2b2 commit 627d20d
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 69 deletions.
53 changes: 34 additions & 19 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)),
Expand Down Expand Up @@ -1184,18 +1175,42 @@ 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 {
require!(
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 {
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_codegen_ssa/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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}`
Expand Down
12 changes: 2 additions & 10 deletions compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
20 changes: 12 additions & 8 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand All @@ -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 => {
Expand Down
10 changes: 4 additions & 6 deletions src/tools/miri/src/shims/intrinsics/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down Expand Up @@ -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)?;
Expand Down
8 changes: 8 additions & 0 deletions src/tools/miri/tests/fail/intrinsics/simd-extract.rs
Original file line number Diff line number Diff line change
@@ -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
}
15 changes: 15 additions & 0 deletions src/tools/miri/tests/fail/intrinsics/simd-extract.stderr
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -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)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -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)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -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)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -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)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -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)
| ^^^^^^^^^^^^^^^^^^^
Expand All @@ -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`.

0 comments on commit 627d20d

Please sign in to comment.