Skip to content

Commit 2a7c322

Browse files
committed
Auto merge of #359 - Nilstrieb:retag-me-im-a-field, r=Amanieu
Fix issue with field retagging in scopeguard With field retagging in SB, this causes UB because the read out value is invalidated by the move into `mem::forget`. Using `ManuallyDrop<T>` avoids the problem. With that issue fixed, we can now enable field retagging in CI. Field retagging is required to justify some of the `noalias` optimizations that rustc performs currently. <details> <summary>Miri error</summary> ```rust Undefined Behavior: trying to retag from <565074> for Unique permission at alloc212719[0x20], but that tag does not exist in the borrow stack for this location --> src/scopeguard.rs:40:13 | 40 | value | ^^^^^ | | | trying to retag from <565074> for Unique permission at alloc212719[0x20], but that tag does not exist in the borrow stack for this location | this error occurs as part of retag at alloc212719[0x20..0x40] | = 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: <565074> was created by a Unique retag at offsets [0x20..0x40] --> src/scopeguard.rs:33:25 | 33 | let value = ptr::read(&guard.value); | ^^^^^^^^^^^^^^^^^^^^^^^ help: <565074> was later invalidated at offsets [0x20..0x40] by a Unique retag --> src/scopeguard.rs:39:25 | 39 | mem::forget(guard); | ^^^^^ = note: backtrace: = note: inside `scopeguard::ScopeGuard::<&mut raw::RawTable<(i32, i32)>, [closure@src/raw/mod.rs:1637:45: 1637:52]>::into_inner` at src/scopeguard.rs:40:13 note: inside `<raw::RawTable<(i32, i32)> as core::clone::Clone>::clone_from` at src/raw/mod.rs:1671:17 --> src/raw/mod.rs:1671:17 | 1671 | ScopeGuard::into_inner(self_); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: inside `<map::HashMap<i32, i32> as core::clone::Clone>::clone_from` at src/map.rs:202:9 --> src/map.rs:202:9 | 202 | self.table.clone_from(&source.table); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: inside `map::test_map::test_clone_from` at src/map.rs:6692:9 --> src/map.rs:6692:9 | 6692 | m2.clone_from(&m); | ^^^^^^^^^^^^^^^^^ note: inside closure at src/map.rs:6684:5 --> src/map.rs:6684:5 | 6683 | #[test] | ------- in this procedural macro expansion 6684 | / fn test_clone_from() { 6685 | | let mut m = HashMap::new(); 6686 | | let mut m2 = HashMap::new(); 6687 | | assert_eq!(m.len(), 0); ... | 6695 | | assert_eq!(m2.len(), 2); 6696 | | } | |_____^ = note: this error originates in the attribute macro `test` (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 ``` </details>
2 parents ea7c3ba + 1f751c6 commit 2a7c322

File tree

2 files changed

+7
-9
lines changed

2 files changed

+7
-9
lines changed

ci/miri.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ rustup toolchain install nightly --component miri
99
rustup override set nightly
1010
cargo miri setup
1111

12-
cargo miri test
12+
MIRIFLAGS='-Zmiri-retag-fields' cargo miri test

src/scopeguard.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Extracted from the scopeguard crate
22
use core::{
3-
mem,
3+
mem::ManuallyDrop,
44
ops::{Deref, DerefMut},
55
ptr,
66
};
@@ -28,15 +28,13 @@ where
2828
#[inline]
2929
pub fn into_inner(guard: Self) -> T {
3030
// Cannot move out of Drop-implementing types, so
31-
// ptr::read the value and forget the guard.
31+
// ptr::read the value out of a ManuallyDrop<Self>
32+
// Don't use mem::forget as that might invalidate value
33+
let guard = ManuallyDrop::new(guard);
3234
unsafe {
3335
let value = ptr::read(&guard.value);
34-
// read the closure so that it is dropped, and assign it to a local
35-
// variable to ensure that it is only dropped after the guard has
36-
// been forgotten. (In case the Drop impl of the closure, or that
37-
// of any consumed captured variable, panics).
38-
let _dropfn = ptr::read(&guard.dropfn);
39-
mem::forget(guard);
36+
// read the closure so that it is dropped
37+
let _ = ptr::read(&guard.dropfn);
4038
value
4139
}
4240
}

0 commit comments

Comments
 (0)