1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
//! Traits and types helping with using uninitialized memory safely. //! //! This crate provides several traits and types that make working with //! uninitialized memory safer. They avoid memory bugs like accidentally //! writing uninitialized value into initialized memory, reading uninitialized //! memory, etc. They also provide strong guarantees for other safe code, which //! is expressed as `unsafe` traits. //! //! Since uninitialized values make most sense when it comes to large objects, //! the main focus is on slices and arrays. For instance, you can initialize //! `Box<[T]>` or `Box<[T; N]>` after it was allocated, avoiding copying. //! Unfortunately that part isn't quite perfect right now, but it does seem to //! work correctly. //! //! The crate is `no_std`-compatible and `alloc`-compatible, of course. #![deny(missing_docs)] #![no_std] #[cfg(feature = "alloc")] extern crate alloc; #[cfg(feature = "std")] extern crate std; pub mod deref_markers; mod borrow; pub mod zeroed; pub mod slice; #[cfg(feature = "alloc")] pub mod boxed; pub mod cast; use core::mem::MaybeUninit; use core::ptr::NonNull; pub use borrow::{BorrowUninit, BorrowOut}; /// Mutable reference wrapper that only allows writing valid values to the /// memory location. /// /// This is used for values that might be borowed from either `T` or /// `MaybeUninit<T>`. /// /// One would normally expect this to be `&mut MaybeUninit<T>`, however, /// that wouldn't be sound. Consider this code: /// /// ```should_panic /// use core::mem::MaybeUninit; /// /// fn cast_mut<T>(val: &mut T) -> &mut MaybeUninit<T> { /// unsafe { /// core::mem::transmute(val) /// } /// } /// /// // No unsafe code here /// fn main() { /// let mut message = "Hello world!".to_string(); /// core::mem::replace(cast_mut(&mut message), MaybeUninit::uninit()); /// println!("This is now garbage: {}", message); /// } /// ``` /// /// The code above triggers UB. Thus the users of the reference must be /// prevented from writing invalid values into the memory location. That's only /// possible by creating a newtype like this one. /// /// While the newtype itself doesn't track initializedness, so its use may be /// limited in safe code, it's a base building block allowing sound /// implementations of wrappers tracking initializedness. pub struct Out<'a, T>(&'a mut MaybeUninit<T>); impl<'a, T> Out<'a, T> { /// Writes a valid value to given memory location, initializing it. pub fn write(self, value: T) -> &'a mut T { unsafe { *self.0 = MaybeUninit::new(value); self.into_assume_init() } } /// Writes a valid value to given memory location, initializing it. /// /// This method is same as `write`, it just reborows the reference instead /// of consuming it. pub fn write_mut(&mut self, value: T) -> &mut T { unsafe { *self.0 = MaybeUninit::new(value); self.assume_init_mut() } } /// Turns the wrapper into reference assuming the value was initialized. /// /// # Safety /// /// Calling this function if no value was written is UB. pub unsafe fn into_assume_init(self) -> &'a mut T { &mut *(self.0 as *mut MaybeUninit<T> as *mut T) } /// Returns mutable non-null pointer to the value. pub fn as_non_null(&mut self) -> NonNull<T> { <NonNull<MaybeUninit<T>>>::from(&mut *self.0).cast() } /// Returns mutable raw pointer to the value. /// /// Note that this is in fact non-null, it's just sometimes more useful than /// `as_non_null`. pub fn as_mut_ptr(&mut self) -> *mut T { self.0 as *mut MaybeUninit<T> as *mut T } /// Overwrites the value with all zeroes. pub fn write_zeroes(&mut self) -> &mut T where T: zeroed::ZeroValid { use crate::zeroed::ZeroValid; unsafe { self.0.write_zeroes(); self.0.assume_init_mut() } } /// Overwrites the value with all zeroes. /// /// Consumes the referenceto to preserve the lifetime pub fn into_zeroed(self) -> &'a mut T where T: zeroed::ZeroValid { use crate::zeroed::ZeroValid; unsafe { self.0.write_zeroes(); self.0.assume_init_mut() } } } impl<'a, T> From<&'a mut T> for Out<'a, T> { fn from(value: &'a mut T) -> Self { unsafe { Out(&mut *(value as *mut T as *mut MaybeUninit<T>)) } } } impl<'a, T> From<&'a mut MaybeUninit<T>> for Out<'a, T> { fn from(value: &'a mut MaybeUninit<T>) -> Self { Out(value) } } unsafe impl<'a, T> BorrowUninit<T> for Out<'a, T> { fn borrow_uninit(&self) -> &MaybeUninit<T> { self.0 } } unsafe impl<'a, T> BorrowOut<T> for Out<'a, T> { fn borrow_out(&mut self) -> Out<'_, T> { self.0.into() } }