diff options
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/fs.rs | 27 | ||||
| -rw-r--r-- | library/std/src/lib.rs | 7 | ||||
| -rw-r--r-- | library/std/src/num/f128.rs (renamed from library/std/src/f128.rs) | 2 | ||||
| -rw-r--r-- | library/std/src/num/f16.rs (renamed from library/std/src/f16.rs) | 2 | ||||
| -rw-r--r-- | library/std/src/num/f32.rs (renamed from library/std/src/f32.rs) | 18 | ||||
| -rw-r--r-- | library/std/src/num/f64.rs (renamed from library/std/src/f64.rs) | 18 | ||||
| -rw-r--r-- | library/std/src/num/mod.rs (renamed from library/std/src/num.rs) | 0 | ||||
| -rw-r--r-- | library/std/src/sys/thread_local/native/lazy.rs | 80 |
8 files changed, 103 insertions, 51 deletions
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 8ed5800e9d0..711efc7d011 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2915,17 +2915,28 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> { /// /// # Platform-specific behavior /// -/// This function currently corresponds to `openat`, `fdopendir`, `unlinkat` and `lstat` functions -/// on Unix (except for REDOX) and the `CreateFileW`, `GetFileInformationByHandleEx`, -/// `SetFileInformationByHandle`, and `NtCreateFile` functions on Windows. Note that, this -/// [may change in the future][changes]. +/// These implementation details [may change in the future][changes]. +/// +/// - "Unix-like": By default, this function currently corresponds to +/// `openat`, `fdopendir`, `unlinkat` and `lstat` +/// on Unix-family platforms, except where noted otherwise. +/// - "Windows": This function currently corresponds to `CreateFileW`, +/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile`. +/// +/// ## Time-of-check to time-of-use (TOCTOU) race conditions +/// On a few platforms there is no way to remove a directory's contents without following symlinks +/// unless you perform a check and then operate on paths based on that directory. +/// This allows concurrently-running code to replace the directory with a symlink after the check, +/// causing a removal to instead operate on a path based on the symlink. This is a TOCTOU race. +/// By default, `fs::remove_dir_all` protects against a symlink TOCTOU race on all platforms +/// except the following. It should not be used in security-sensitive contexts on these platforms: +/// - Miri: Even when emulating targets where the underlying implementation will protect against +/// TOCTOU races, Miri will not do so. +/// - Redox OS: This function does not protect against TOCTOU races, as Redox does not implement +/// the required platform support to do so. /// /// [changes]: io#platform-specific-behavior /// -/// On REDOX, as well as when running in Miri for any target, this function is not protected against -/// time-of-check to time-of-use (TOCTOU) race conditions, and should not be used in -/// security-sensitive code on those platforms. All other platforms are protected. -/// /// # Errors /// /// See [`fs::remove_file`] and [`fs::remove_dir`]. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 4b2418a4985..74a34339860 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -335,6 +335,7 @@ #![feature(bstr_internals)] #![feature(char_internals)] #![feature(clone_to_uninit)] +#![feature(const_float_round_methods)] #![feature(core_intrinsics)] #![feature(core_io_borrowed_buf)] #![feature(duration_constants)] @@ -585,11 +586,13 @@ pub use alloc_crate::string; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::vec; -#[unstable(feature = "f128", issue = "116909")] +#[path = "num/f128.rs"] pub mod f128; -#[unstable(feature = "f16", issue = "116909")] +#[path = "num/f16.rs"] pub mod f16; +#[path = "num/f32.rs"] pub mod f32; +#[path = "num/f64.rs"] pub mod f64; #[macro_use] diff --git a/library/std/src/f128.rs b/library/std/src/num/f128.rs index bb4acde4822..c0190de089f 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/num/f128.rs @@ -4,6 +4,8 @@ //! //! Mathematically significant numbers are provided in the `consts` sub-module. +#![unstable(feature = "f128", issue = "116909")] + #[unstable(feature = "f128", issue = "116909")] pub use core::f128::consts; diff --git a/library/std/src/f16.rs b/library/std/src/num/f16.rs index 4792eac1f9e..4a4a8fd839a 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/num/f16.rs @@ -4,6 +4,8 @@ //! //! Mathematically significant numbers are provided in the `consts` sub-module. +#![unstable(feature = "f16", issue = "116909")] + #[unstable(feature = "f16", issue = "116909")] pub use core::f16::consts; diff --git a/library/std/src/f32.rs b/library/std/src/num/f32.rs index 5210e75ec45..b7f6529ac40 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/num/f32.rs @@ -44,8 +44,9 @@ impl f32 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn floor(self) -> f32 { + pub const fn floor(self) -> f32 { core::f32::math::floor(self) } @@ -66,8 +67,9 @@ impl f32 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn ceil(self) -> f32 { + pub const fn ceil(self) -> f32 { core::f32::math::ceil(self) } @@ -94,8 +96,9 @@ impl f32 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn round(self) -> f32 { + pub const fn round(self) -> f32 { core::f32::math::round(self) } @@ -120,8 +123,9 @@ impl f32 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "round_ties_even", since = "1.77.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn round_ties_even(self) -> f32 { + pub const fn round_ties_even(self) -> f32 { core::f32::math::round_ties_even(self) } @@ -145,8 +149,9 @@ impl f32 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn trunc(self) -> f32 { + pub const fn trunc(self) -> f32 { core::f32::math::trunc(self) } @@ -168,8 +173,9 @@ impl f32 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn fract(self) -> f32 { + pub const fn fract(self) -> f32 { core::f32::math::fract(self) } diff --git a/library/std/src/f64.rs b/library/std/src/num/f64.rs index f837800d663..75e35a8db33 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/num/f64.rs @@ -44,8 +44,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn floor(self) -> f64 { + pub const fn floor(self) -> f64 { core::f64::math::floor(self) } @@ -66,8 +67,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn ceil(self) -> f64 { + pub const fn ceil(self) -> f64 { core::f64::math::ceil(self) } @@ -94,8 +96,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn round(self) -> f64 { + pub const fn round(self) -> f64 { core::f64::math::round(self) } @@ -120,8 +123,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "round_ties_even", since = "1.77.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn round_ties_even(self) -> f64 { + pub const fn round_ties_even(self) -> f64 { core::f64::math::round_ties_even(self) } @@ -145,8 +149,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn trunc(self) -> f64 { + pub const fn trunc(self) -> f64 { core::f64::math::trunc(self) } @@ -168,8 +173,9 @@ impl f64 { #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")] #[inline] - pub fn fract(self) -> f64 { + pub const fn fract(self) -> f64 { core::f64::math::fract(self) } diff --git a/library/std/src/num.rs b/library/std/src/num/mod.rs index ffb8789c906..ffb8789c906 100644 --- a/library/std/src/num.rs +++ b/library/std/src/num/mod.rs diff --git a/library/std/src/sys/thread_local/native/lazy.rs b/library/std/src/sys/thread_local/native/lazy.rs index 51294285ba0..b556dd9aa25 100644 --- a/library/std/src/sys/thread_local/native/lazy.rs +++ b/library/std/src/sys/thread_local/native/lazy.rs @@ -1,9 +1,9 @@ -use crate::cell::UnsafeCell; -use crate::hint::unreachable_unchecked; +use crate::cell::{Cell, UnsafeCell}; +use crate::mem::MaybeUninit; use crate::ptr; use crate::sys::thread_local::{abort_on_dtor_unwind, destructors}; -pub unsafe trait DestroyedState: Sized { +pub unsafe trait DestroyedState: Sized + Copy { fn register_dtor<T>(s: &Storage<T, Self>); } @@ -19,15 +19,17 @@ unsafe impl DestroyedState for () { } } -enum State<T, D> { - Initial, - Alive(T), +#[derive(Copy, Clone)] +enum State<D> { + Uninitialized, + Alive, Destroyed(D), } #[allow(missing_debug_implementations)] pub struct Storage<T, D> { - state: UnsafeCell<State<T, D>>, + state: Cell<State<D>>, + value: UnsafeCell<MaybeUninit<T>>, } impl<T, D> Storage<T, D> @@ -35,7 +37,10 @@ where D: DestroyedState, { pub const fn new() -> Storage<T, D> { - Storage { state: UnsafeCell::new(State::Initial) } + Storage { + state: Cell::new(State::Uninitialized), + value: UnsafeCell::new(MaybeUninit::uninit()), + } } /// Gets a pointer to the TLS value, potentially initializing it with the @@ -49,35 +54,49 @@ where /// The `self` reference must remain valid until the TLS destructor is run. #[inline] pub unsafe fn get_or_init(&self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T { - let state = unsafe { &*self.state.get() }; - match state { - State::Alive(v) => v, - State::Destroyed(_) => ptr::null(), - State::Initial => unsafe { self.initialize(i, f) }, + if let State::Alive = self.state.get() { + self.value.get().cast() + } else { + unsafe { self.get_or_init_slow(i, f) } } } + /// # Safety + /// The `self` reference must remain valid until the TLS destructor is run. #[cold] - unsafe fn initialize(&self, i: Option<&mut Option<T>>, f: impl FnOnce() -> T) -> *const T { - // Perform initialization + unsafe fn get_or_init_slow( + &self, + i: Option<&mut Option<T>>, + f: impl FnOnce() -> T, + ) -> *const T { + match self.state.get() { + State::Uninitialized => {} + State::Alive => return self.value.get().cast(), + State::Destroyed(_) => return ptr::null(), + } let v = i.and_then(Option::take).unwrap_or_else(f); - let old = unsafe { self.state.get().replace(State::Alive(v)) }; - match old { + // SAFETY: we cannot be inside a `LocalKey::with` scope, as the initializer + // has already returned and the next scope only starts after we return + // the pointer. Therefore, there can be no references to the old value, + // even if it was initialized. Thus because we are !Sync we have exclusive + // access to self.value and may replace it. + let mut old_value = unsafe { self.value.get().replace(MaybeUninit::new(v)) }; + match self.state.replace(State::Alive) { // If the variable is not being recursively initialized, register // the destructor. This might be a noop if the value does not need // destruction. - State::Initial => D::register_dtor(self), - // Else, drop the old value. This might be changed to a panic. - val => drop(val), - } + State::Uninitialized => D::register_dtor(self), - // SAFETY: the state was just set to `Alive` - unsafe { - let State::Alive(v) = &*self.state.get() else { unreachable_unchecked() }; - v + // Recursive initialization, we only need to drop the old value + // as we've already registered the destructor. + State::Alive => unsafe { old_value.assume_init_drop() }, + + State::Destroyed(_) => unreachable!(), } + + self.value.get().cast() } } @@ -92,9 +111,12 @@ unsafe extern "C" fn destroy<T>(ptr: *mut u8) { // Print a nice abort message if a panic occurs. abort_on_dtor_unwind(|| { let storage = unsafe { &*(ptr as *const Storage<T, ()>) }; - // Update the state before running the destructor as it may attempt to - // access the variable. - let val = unsafe { storage.state.get().replace(State::Destroyed(())) }; - drop(val); + if let State::Alive = storage.state.replace(State::Destroyed(())) { + // SAFETY: we ensured the state was Alive so the value was initialized. + // We also updated the state to Destroyed to prevent the destructor + // from accessing the thread-local variable, as this would violate + // the exclusive access provided by &mut T in Drop::drop. + unsafe { (*storage.value.get()).assume_init_drop() } + } }) } |
