Skip to content

Commit 19ccb6c

Browse files
committed
Auto merge of rust-lang#79838 - Mark-Simulacrum:beta-next, r=Mark-Simulacrum
[beta] backports * [beta] always disable copy_file_range to avoid EOVERFLOW errors rust-lang#79008 * Enforce no-move rule of ReentrantMutex using Pin and fix UB in stdio rust-lang#77801 * bootstrap: use the same version number for rustc and cargo rust-lang#79133 * [beta] Revert "Enable ASLR for windows-gnu" rust-lang#79141 * [beta] revert rust-lang#78790, vendor libtest for rustc-src rust-lang#79571 * Mirror centos vault to S3 rust-lang#79435 * [beta] Update cargo rust-lang#79739 This also bumps to non-dev stable compiler. r? `@ghost`
2 parents bd26e4e + b857cb6 commit 19ccb6c

File tree

15 files changed

+151
-177
lines changed

15 files changed

+151
-177
lines changed

compiler/rustc_target/src/spec/windows_gnu_base.rs

-4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ pub fn opts() -> TargetOptions {
1111
"-fno-use-linker-plugin".to_string(),
1212
// Always enable DEP (NX bit) when it is available
1313
"-Wl,--nxcompat".to_string(),
14-
// Enable ASLR
15-
"-Wl,--dynamicbase".to_string(),
16-
// ASLR will rebase it anyway so leaving that option enabled only leads to confusion
17-
"-Wl,--disable-auto-image-base".to_string(),
1814
],
1915
);
2016

compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ use crate::spec::{LinkerFlavor, LldFlavor, Target};
33
pub fn target() -> Target {
44
let mut base = super::windows_gnu_base::opts();
55
base.cpu = "x86-64".to_string();
6-
let gcc_pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap();
7-
gcc_pre_link_args.push("-m64".to_string());
8-
// Use high-entropy 64 bit address space for ASLR
9-
gcc_pre_link_args.push("-Wl,--high-entropy-va".to_string());
6+
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
107
base.pre_link_args
118
.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pep".to_string()]);
129
base.max_atomic_width = Some(64);

compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ use crate::spec::{LinkerFlavor, LldFlavor, Target};
33
pub fn target() -> Target {
44
let mut base = super::windows_uwp_gnu_base::opts();
55
base.cpu = "x86-64".to_string();
6-
let gcc_pre_link_args = base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap();
7-
gcc_pre_link_args.push("-m64".to_string());
8-
// Use high-entropy 64 bit address space for ASLR
9-
gcc_pre_link_args.push("-Wl,--high-entropy-va".to_string());
6+
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
107
base.pre_link_args
118
.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pep".to_string()]);
129
base.max_atomic_width = Some(64);

library/std/src/io/stdio.rs

+32-32
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::cell::RefCell;
99
use crate::fmt;
1010
use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter};
1111
use crate::lazy::SyncOnceCell;
12+
use crate::pin::Pin;
1213
use crate::sync::atomic::{AtomicBool, Ordering};
1314
use crate::sync::{Mutex, MutexGuard};
1415
use crate::sys::stdio;
@@ -488,7 +489,7 @@ pub struct Stdout {
488489
// FIXME: this should be LineWriter or BufWriter depending on the state of
489490
// stdout (tty or not). Note that if this is not line buffered it
490491
// should also flush-on-panic or some form of flush-on-abort.
491-
inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
492+
inner: Pin<&'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
492493
}
493494

494495
/// A locked reference to the `Stdout` handle.
@@ -548,25 +549,29 @@ pub struct StdoutLock<'a> {
548549
pub fn stdout() -> Stdout {
549550
static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> =
550551
SyncOnceCell::new();
552+
553+
fn cleanup() {
554+
if let Some(instance) = INSTANCE.get() {
555+
// Flush the data and disable buffering during shutdown
556+
// by replacing the line writer by one with zero
557+
// buffering capacity.
558+
// We use try_lock() instead of lock(), because someone
559+
// might have leaked a StdoutLock, which would
560+
// otherwise cause a deadlock here.
561+
if let Some(lock) = Pin::static_ref(instance).try_lock() {
562+
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
563+
}
564+
}
565+
}
566+
551567
Stdout {
552-
inner: INSTANCE.get_or_init(|| unsafe {
553-
let _ = sys_common::at_exit(|| {
554-
if let Some(instance) = INSTANCE.get() {
555-
// Flush the data and disable buffering during shutdown
556-
// by replacing the line writer by one with zero
557-
// buffering capacity.
558-
// We use try_lock() instead of lock(), because someone
559-
// might have leaked a StdoutLock, which would
560-
// otherwise cause a deadlock here.
561-
if let Some(lock) = instance.try_lock() {
562-
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
563-
}
564-
}
565-
});
566-
let r = ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())));
567-
r.init();
568-
r
569-
}),
568+
inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
569+
|| unsafe {
570+
let _ = sys_common::at_exit(cleanup);
571+
ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))
572+
},
573+
|mutex| unsafe { mutex.init() },
574+
),
570575
}
571576
}
572577

@@ -698,7 +703,7 @@ impl fmt::Debug for StdoutLock<'_> {
698703
/// an error.
699704
#[stable(feature = "rust1", since = "1.0.0")]
700705
pub struct Stderr {
701-
inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
706+
inner: Pin<&'static ReentrantMutex<RefCell<StderrRaw>>>,
702707
}
703708

704709
/// A locked reference to the `Stderr` handle.
@@ -754,21 +759,16 @@ pub struct StderrLock<'a> {
754759
/// ```
755760
#[stable(feature = "rust1", since = "1.0.0")]
756761
pub fn stderr() -> Stderr {
757-
// Note that unlike `stdout()` we don't use `Lazy` here which registers a
758-
// destructor. Stderr is not buffered nor does the `stderr_raw` type consume
759-
// any owned resources, so there's no need to run any destructors at some
760-
// point in the future.
761-
//
762-
// This has the added benefit of allowing `stderr` to be usable during
763-
// process shutdown as well!
762+
// Note that unlike `stdout()` we don't use `at_exit` here to register a
763+
// destructor. Stderr is not buffered , so there's no need to run a
764+
// destructor for flushing the buffer
764765
static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<StderrRaw>>> = SyncOnceCell::new();
765766

766767
Stderr {
767-
inner: INSTANCE.get_or_init(|| unsafe {
768-
let r = ReentrantMutex::new(RefCell::new(stderr_raw()));
769-
r.init();
770-
r
771-
}),
768+
inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
769+
|| unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) },
770+
|mutex| unsafe { mutex.init() },
771+
),
772772
}
773773
}
774774

library/std/src/lazy.rs

+55
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010
mem::MaybeUninit,
1111
ops::{Deref, Drop},
1212
panic::{RefUnwindSafe, UnwindSafe},
13+
pin::Pin,
1314
sync::Once,
1415
};
1516

@@ -297,6 +298,60 @@ impl<T> SyncOnceCell<T> {
297298
Ok(unsafe { self.get_unchecked() })
298299
}
299300

301+
/// Internal-only API that gets the contents of the cell, initializing it
302+
/// in two steps with `f` and `g` if the cell was empty.
303+
///
304+
/// `f` is called to construct the value, which is then moved into the cell
305+
/// and given as a (pinned) mutable reference to `g` to finish
306+
/// initialization.
307+
///
308+
/// This allows `g` to inspect an manipulate the value after it has been
309+
/// moved into its final place in the cell, but before the cell is
310+
/// considered initialized.
311+
///
312+
/// # Panics
313+
///
314+
/// If `f` or `g` panics, the panic is propagated to the caller, and the
315+
/// cell remains uninitialized.
316+
///
317+
/// With the current implementation, if `g` panics, the value from `f` will
318+
/// not be dropped. This should probably be fixed if this is ever used for
319+
/// a type where this matters.
320+
///
321+
/// It is an error to reentrantly initialize the cell from `f`. The exact
322+
/// outcome is unspecified. Current implementation deadlocks, but this may
323+
/// be changed to a panic in the future.
324+
pub(crate) fn get_or_init_pin<F, G>(self: Pin<&Self>, f: F, g: G) -> Pin<&T>
325+
where
326+
F: FnOnce() -> T,
327+
G: FnOnce(Pin<&mut T>),
328+
{
329+
if let Some(value) = self.get_ref().get() {
330+
// SAFETY: The inner value was already initialized, and will not be
331+
// moved anymore.
332+
return unsafe { Pin::new_unchecked(value) };
333+
}
334+
335+
let slot = &self.value;
336+
337+
// Ignore poisoning from other threads
338+
// If another thread panics, then we'll be able to run our closure
339+
self.once.call_once_force(|_| {
340+
let value = f();
341+
// SAFETY: We use the Once (self.once) to guarantee unique access
342+
// to the UnsafeCell (slot).
343+
let value: &mut T = unsafe { (&mut *slot.get()).write(value) };
344+
// SAFETY: The value has been written to its final place in
345+
// self.value. We do not to move it anymore, which we promise here
346+
// with a Pin<&mut T>.
347+
g(unsafe { Pin::new_unchecked(value) });
348+
});
349+
350+
// SAFETY: The inner value has been initialized, and will not be moved
351+
// anymore.
352+
unsafe { Pin::new_unchecked(self.get_ref().get_unchecked()) }
353+
}
354+
300355
/// Consumes the `SyncOnceCell`, returning the wrapped value. Returns
301356
/// `None` if the cell was empty.
302357
///

library/std/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@
267267
#![feature(format_args_nl)]
268268
#![feature(gen_future)]
269269
#![feature(generator_trait)]
270+
#![feature(get_mut_unchecked)]
270271
#![feature(global_asm)]
271272
#![feature(hashmap_internals)]
272273
#![feature(int_error_internals)]
@@ -293,6 +294,7 @@
293294
#![feature(panic_info_message)]
294295
#![feature(panic_internals)]
295296
#![feature(panic_unwind)]
297+
#![feature(pin_static_ref)]
296298
#![feature(prelude_import)]
297299
#![feature(ptr_internals)]
298300
#![feature(raw)]

library/std/src/sys/unix/fs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
12091209

12101210
// Kernel prior to 4.5 don't have copy_file_range
12111211
// We store the availability in a global to avoid unnecessary syscalls
1212-
static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(true);
1212+
static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(false);
12131213

12141214
unsafe fn copy_file_range(
12151215
fd_in: libc::c_int,

library/std/src/sys_common/remutex.rs

+20-35
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#[cfg(all(test, not(target_os = "emscripten")))]
22
mod tests;
33

4-
use crate::fmt;
5-
use crate::marker;
4+
use crate::marker::PhantomPinned;
65
use crate::ops::Deref;
76
use crate::panic::{RefUnwindSafe, UnwindSafe};
7+
use crate::pin::Pin;
88
use crate::sys::mutex as sys;
99

1010
/// A re-entrant mutual exclusion
@@ -15,6 +15,7 @@ use crate::sys::mutex as sys;
1515
pub struct ReentrantMutex<T> {
1616
inner: sys::ReentrantMutex,
1717
data: T,
18+
_pinned: PhantomPinned,
1819
}
1920

2021
unsafe impl<T: Send> Send for ReentrantMutex<T> {}
@@ -37,10 +38,10 @@ impl<T> RefUnwindSafe for ReentrantMutex<T> {}
3738
/// guarded data.
3839
#[must_use = "if unused the ReentrantMutex will immediately unlock"]
3940
pub struct ReentrantMutexGuard<'a, T: 'a> {
40-
lock: &'a ReentrantMutex<T>,
41+
lock: Pin<&'a ReentrantMutex<T>>,
4142
}
4243

43-
impl<T> !marker::Send for ReentrantMutexGuard<'_, T> {}
44+
impl<T> !Send for ReentrantMutexGuard<'_, T> {}
4445

4546
impl<T> ReentrantMutex<T> {
4647
/// Creates a new reentrant mutex in an unlocked state.
@@ -51,7 +52,11 @@ impl<T> ReentrantMutex<T> {
5152
/// once this mutex is in its final resting place, and only then are the
5253
/// lock/unlock methods safe.
5354
pub const unsafe fn new(t: T) -> ReentrantMutex<T> {
54-
ReentrantMutex { inner: sys::ReentrantMutex::uninitialized(), data: t }
55+
ReentrantMutex {
56+
inner: sys::ReentrantMutex::uninitialized(),
57+
data: t,
58+
_pinned: PhantomPinned,
59+
}
5560
}
5661

5762
/// Initializes this mutex so it's ready for use.
@@ -60,8 +65,8 @@ impl<T> ReentrantMutex<T> {
6065
///
6166
/// Unsafe to call more than once, and must be called after this will no
6267
/// longer move in memory.
63-
pub unsafe fn init(&self) {
64-
self.inner.init();
68+
pub unsafe fn init(self: Pin<&mut Self>) {
69+
self.get_unchecked_mut().inner.init()
6570
}
6671

6772
/// Acquires a mutex, blocking the current thread until it is able to do so.
@@ -76,9 +81,9 @@ impl<T> ReentrantMutex<T> {
7681
/// If another user of this mutex panicked while holding the mutex, then
7782
/// this call will return failure if the mutex would otherwise be
7883
/// acquired.
79-
pub fn lock(&self) -> ReentrantMutexGuard<'_, T> {
84+
pub fn lock(self: Pin<&Self>) -> ReentrantMutexGuard<'_, T> {
8085
unsafe { self.inner.lock() }
81-
ReentrantMutexGuard::new(&self)
86+
ReentrantMutexGuard { lock: self }
8287
}
8388

8489
/// Attempts to acquire this lock.
@@ -93,8 +98,12 @@ impl<T> ReentrantMutex<T> {
9398
/// If another user of this mutex panicked while holding the mutex, then
9499
/// this call will return failure if the mutex would otherwise be
95100
/// acquired.
96-
pub fn try_lock(&self) -> Option<ReentrantMutexGuard<'_, T>> {
97-
if unsafe { self.inner.try_lock() } { Some(ReentrantMutexGuard::new(&self)) } else { None }
101+
pub fn try_lock(self: Pin<&Self>) -> Option<ReentrantMutexGuard<'_, T>> {
102+
if unsafe { self.inner.try_lock() } {
103+
Some(ReentrantMutexGuard { lock: self })
104+
} else {
105+
None
106+
}
98107
}
99108
}
100109

@@ -107,30 +116,6 @@ impl<T> Drop for ReentrantMutex<T> {
107116
}
108117
}
109118

110-
impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> {
111-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112-
match self.try_lock() {
113-
Some(guard) => f.debug_struct("ReentrantMutex").field("data", &*guard).finish(),
114-
None => {
115-
struct LockedPlaceholder;
116-
impl fmt::Debug for LockedPlaceholder {
117-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118-
f.write_str("<locked>")
119-
}
120-
}
121-
122-
f.debug_struct("ReentrantMutex").field("data", &LockedPlaceholder).finish()
123-
}
124-
}
125-
}
126-
}
127-
128-
impl<'mutex, T> ReentrantMutexGuard<'mutex, T> {
129-
fn new(lock: &'mutex ReentrantMutex<T>) -> ReentrantMutexGuard<'mutex, T> {
130-
ReentrantMutexGuard { lock }
131-
}
132-
}
133-
134119
impl<T> Deref for ReentrantMutexGuard<'_, T> {
135120
type Target = T;
136121

0 commit comments

Comments
 (0)