mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-30 08:34:07 +00:00
Retag as FnEntry on drop_in_place
This commit is contained in:
parent
49143814e1
commit
102040ce76
@ -176,7 +176,33 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
||||
|
||||
if ty.is_some() {
|
||||
// The first argument (index 0), but add 1 for the return value.
|
||||
let dropee_ptr = Place::from(Local::new(1 + 0));
|
||||
let mut dropee_ptr = Place::from(Local::new(1 + 0));
|
||||
if tcx.sess.opts.unstable_opts.mir_emit_retag {
|
||||
// We want to treat the function argument as if it was passed by `&mut`. As such, we
|
||||
// generate
|
||||
// ```
|
||||
// temp = &mut *arg;
|
||||
// Retag(temp, FnEntry)
|
||||
// ```
|
||||
// It's important that we do this first, before anything that depends on `dropee_ptr`
|
||||
// has been put into the body.
|
||||
let reborrow = Rvalue::Ref(
|
||||
tcx.lifetimes.re_erased,
|
||||
BorrowKind::Mut { allow_two_phase_borrow: false },
|
||||
tcx.mk_place_deref(dropee_ptr),
|
||||
);
|
||||
let ref_ty = reborrow.ty(body.local_decls(), tcx);
|
||||
dropee_ptr = body.local_decls.push(LocalDecl::new(ref_ty, span)).into();
|
||||
let new_statements = [
|
||||
StatementKind::Assign(Box::new((dropee_ptr, reborrow))),
|
||||
StatementKind::Retag(RetagKind::FnEntry, Box::new(dropee_ptr)),
|
||||
];
|
||||
for s in new_statements {
|
||||
body.basic_blocks_mut()[START_BLOCK]
|
||||
.statements
|
||||
.push(Statement { source_info, kind: s });
|
||||
}
|
||||
}
|
||||
let patch = {
|
||||
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
||||
let mut elaborator =
|
||||
|
@ -3,11 +3,14 @@
|
||||
fn std::ptr::drop_in_place(_1: *mut Test) -> () {
|
||||
let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _2: &mut Test; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _3: &mut Test; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
let mut _4: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
|
||||
bb0: {
|
||||
_2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
Retag([fn entry] _2); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_3 = &mut (*_2); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
_4 = <Test as Drop>::drop(move _3) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
|
||||
// mir::Constant
|
||||
// + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||
// + literal: Const { ty: for<'a> fn(&'a mut Test) {<Test as Drop>::drop}, val: Value(<ZST>) }
|
||||
|
@ -0,0 +1,27 @@
|
||||
//! Test that drop_in_place retags the entire place,
|
||||
//! invalidating all aliases to it.
|
||||
|
||||
// A zero-sized drop type -- the retagging of `fn drop` itself won't
|
||||
// do anything (since it is zero-sized); we are entirely relying on the retagging
|
||||
// in `drop_in_place` here.
|
||||
#[repr(transparent)]
|
||||
struct HasDrop;
|
||||
impl Drop for HasDrop {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let _val = *P;
|
||||
//~^ ERROR: /not granting access .* because that would remove .* which is protected/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static mut P: *mut u8 = core::ptr::null_mut();
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let mut x = (HasDrop, 0u8);
|
||||
let x = core::ptr::addr_of_mut!(x);
|
||||
P = x.cast();
|
||||
core::ptr::drop_in_place(x);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is protected because it is an argument of call ID
|
||||
--> $DIR/drop_in_place_protector.rs:LL:CC
|
||||
|
|
||||
LL | let _val = *P;
|
||||
| ^^ not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is protected because it is an argument of call ID
|
||||
|
|
||||
= 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: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x1]
|
||||
--> $DIR/drop_in_place_protector.rs:LL:CC
|
||||
|
|
||||
LL | let x = core::ptr::addr_of_mut!(x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: <TAG> is this argument
|
||||
--> $DIR/drop_in_place_protector.rs:LL:CC
|
||||
|
|
||||
LL | core::ptr::drop_in_place(x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: inside `<HasDrop as std::ops::Drop>::drop` at $DIR/drop_in_place_protector.rs:LL:CC
|
||||
= note: inside `std::ptr::drop_in_place::<HasDrop> - shim(Some(HasDrop))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||
= note: inside `std::ptr::drop_in_place::<(HasDrop, u8)> - shim(Some((HasDrop, u8)))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||
note: inside `main` at $DIR/drop_in_place_protector.rs:LL:CC
|
||||
--> $DIR/drop_in_place_protector.rs:LL:CC
|
||||
|
|
||||
LL | core::ptr::drop_in_place(x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the macro `core::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -0,0 +1,19 @@
|
||||
//! Test that drop_in_place mutably retags the entire place,
|
||||
//! ensuring it is writeable
|
||||
|
||||
//@error-pattern: /retag .* for Unique permission .* only grants SharedReadOnly permission/
|
||||
|
||||
#[repr(transparent)]
|
||||
struct HasDrop;
|
||||
|
||||
impl Drop for HasDrop {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let x = (0u8, HasDrop);
|
||||
let x = core::ptr::addr_of!(x);
|
||||
core::ptr::drop_in_place(x.cast_mut());
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
error: Undefined Behavior: trying to retag from <TAG> for Unique permission at ALLOC[0x0], but that tag only grants SharedReadOnly permission for this location
|
||||
--> RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||
|
|
||||
LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| trying to retag from <TAG> for Unique permission at ALLOC[0x0], but that tag only grants SharedReadOnly permission for this location
|
||||
| this error occurs as part of FnEntry retag at ALLOC[0x0..0x1]
|
||||
|
|
||||
= 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: <TAG> was created by a SharedReadOnly retag at offsets [0x0..0x1]
|
||||
--> $DIR/drop_in_place_retag.rs:LL:CC
|
||||
|
|
||||
LL | let x = core::ptr::addr_of!(x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE:
|
||||
= note: inside `std::ptr::drop_in_place::<(u8, HasDrop)> - shim(Some((u8, HasDrop)))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||
note: inside `main` at $DIR/drop_in_place_retag.rs:LL:CC
|
||||
--> $DIR/drop_in_place_retag.rs:LL:CC
|
||||
|
|
||||
LL | core::ptr::drop_in_place(x.cast_mut());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the macro `core::ptr::addr_of` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -0,0 +1,25 @@
|
||||
#[repr(transparent)]
|
||||
struct HasDrop(u8);
|
||||
|
||||
impl Drop for HasDrop {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
#[repr(C, align(2))]
|
||||
struct PartialDrop {
|
||||
a: HasDrop,
|
||||
b: u8,
|
||||
}
|
||||
|
||||
//@error-pattern: /alignment 2 is required/
|
||||
fn main() {
|
||||
unsafe {
|
||||
// Create an unaligned pointer
|
||||
let mut x = [0_u16; 2];
|
||||
let p = core::ptr::addr_of_mut!(x).cast::<u8>();
|
||||
let p = p.add(1);
|
||||
let p = p.cast::<PartialDrop>();
|
||||
|
||||
core::ptr::drop_in_place(p);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required
|
||||
--> RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||
|
|
||||
LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
|
||||
|
|
||||
= 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 `std::ptr::drop_in_place::<PartialDrop> - shim(Some(PartialDrop))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||
note: inside `main` at $DIR/drop_in_place.rs:LL:CC
|
||||
--> $DIR/drop_in_place.rs:LL:CC
|
||||
|
|
||||
LL | core::ptr::drop_in_place(p);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
7
src/tools/miri/tests/pass/drop_in_place_null.rs
Normal file
7
src/tools/miri/tests/pass/drop_in_place_null.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// Make sure that dropping types with no drop glue is DB even for invalid pointers.
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
core::ptr::drop_in_place::<u8>(core::ptr::null_mut());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user