mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-07 12:48:30 +00:00
Auto merge of #116915 - bend-n:unwet, r=saethlin
Add an assume that the index is inbounds to slice::get_unchecked Fixes #116878
This commit is contained in:
commit
85a4bd8f58
@ -233,7 +233,10 @@ unsafe impl<T> SliceIndex<[T]> for usize {
|
|||||||
// cannot be longer than `isize::MAX`. They also guarantee that
|
// cannot be longer than `isize::MAX`. They also guarantee that
|
||||||
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
|
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
|
||||||
// so the call to `add` is safe.
|
// so the call to `add` is safe.
|
||||||
unsafe { slice.as_ptr().add(self) }
|
unsafe {
|
||||||
|
crate::intrinsics::assume(self < slice.len());
|
||||||
|
slice.as_ptr().add(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
//@compile-flags: -Zmiri-strict-provenance
|
//@compile-flags: -Zmiri-strict-provenance
|
||||||
//@error-in-other-file: /retag .* tag does not exist in the borrow stack/
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let a = [1, 2, 3];
|
let a = [1, 2, 3];
|
||||||
let s = &a[0..0];
|
let s = &a[0..0];
|
||||||
assert_eq!(s.len(), 0);
|
assert_eq!(s.len(), 0);
|
||||||
assert_eq!(*s.get_unchecked(1), 2);
|
assert_eq!(*s.as_ptr().add(1), 2); //~ ERROR: /retag .* tag does not exist in the borrow stack/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,22 @@
|
|||||||
error: Undefined Behavior: trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
|
error: Undefined Behavior: trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
|
||||||
--> RUSTLIB/core/src/slice/mod.rs:LL:CC
|
--> $DIR/zst_slice.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | unsafe { &*index.get_unchecked(self) }
|
LL | assert_eq!(*s.as_ptr().add(1), 2);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
|
| trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
|
||||||
| this error occurs as part of retag at ALLOC[0x4..0x8]
|
| this error occurs as part of retag at ALLOC[0x4..0x8]
|
||||||
|
|
|
|
||||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||||
help: <TAG> would have been created here, but this is a zero-size retag ([0x0..0x0]) so the tag in question does not exist anywhere
|
help: <TAG> would have been created here, but this is a zero-size retag ([0x0..0x0]) so the tag in question does not exist anywhere
|
||||||
--> $DIR/zst_slice.rs:LL:CC
|
--> $DIR/zst_slice.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | assert_eq!(*s.get_unchecked(1), 2);
|
LL | assert_eq!(*s.as_ptr().add(1), 2);
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
= note: BACKTRACE (of the first span):
|
= note: BACKTRACE (of the first span):
|
||||||
= note: inside `core::slice::<impl [i32]>::get_unchecked::<usize>` at RUSTLIB/core/src/slice/mod.rs:LL:CC
|
= note: inside `main` at RUSTLIB/core/src/macros/mod.rs:LL:CC
|
||||||
note: inside `main`
|
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
--> $DIR/zst_slice.rs:LL:CC
|
|
||||||
|
|
|
||||||
LL | assert_eq!(*s.get_unchecked(1), 2);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//@compile-flags: -Zmiri-disable-stacked-borrows
|
//@compile-flags: -Zmiri-disable-stacked-borrows
|
||||||
fn main() {
|
fn main() {
|
||||||
let v: Vec<u8> = Vec::with_capacity(10);
|
let v: Vec<u8> = Vec::with_capacity(10);
|
||||||
let undef = unsafe { *v.get_unchecked(5) }; //~ ERROR: uninitialized
|
let undef = unsafe { *v.as_ptr().add(5) }; //~ ERROR: uninitialized
|
||||||
let x = undef + 1;
|
let x = undef + 1;
|
||||||
panic!("this should never print: {}", x);
|
panic!("this should never print: {}", x);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
|
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
|
||||||
--> $DIR/uninit_byte_read.rs:LL:CC
|
--> $DIR/uninit_byte_read.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | let undef = unsafe { *v.get_unchecked(5) };
|
LL | let undef = unsafe { *v.as_ptr().add(5) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
| ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= 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
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
@ -20,8 +20,8 @@ use NaNKind::*;
|
|||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn check_all_outcomes<T: Eq + Hash + fmt::Display>(expected: HashSet<T>, generate: impl Fn() -> T) {
|
fn check_all_outcomes<T: Eq + Hash + fmt::Display>(expected: HashSet<T>, generate: impl Fn() -> T) {
|
||||||
let mut seen = HashSet::new();
|
let mut seen = HashSet::new();
|
||||||
// Let's give it 8x as many tries as we are expecting values.
|
// Let's give it sixteen times as many tries as we are expecting values.
|
||||||
let tries = expected.len() * 8;
|
let tries = expected.len() * 16;
|
||||||
for _ in 0..tries {
|
for _ in 0..tries {
|
||||||
let val = generate();
|
let val = generate();
|
||||||
assert!(expected.contains(&val), "got an unexpected value: {val}");
|
assert!(expected.contains(&val), "got an unexpected value: {val}");
|
||||||
|
13
tests/codegen/issues/issue-116878.rs
Normal file
13
tests/codegen/issues/issue-116878.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// no-system-llvm
|
||||||
|
// compile-flags: -O
|
||||||
|
// ignore-debug: the debug assertions get in the way
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
/// Make sure no bounds checks are emitted after a `get_unchecked`.
|
||||||
|
// CHECK-LABEL: @unchecked_slice_no_bounds_check
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn unchecked_slice_no_bounds_check(s: &[u8]) -> u8 {
|
||||||
|
let a = *s.get_unchecked(1);
|
||||||
|
// CHECK-NOT: panic_bounds_check
|
||||||
|
a + s[0]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user