1 // Copyright 2024 The Fuchsia Authors 2 // 3 // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0 4 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT 5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option. 6 // This file may not be copied, modified, or distributed except according to 7 // those terms. 8 9 #![allow(missing_copy_implementations, missing_debug_implementations, missing_docs)] 10 11 //! The parameterized invariants of a [`Ptr`][super::Ptr]. 12 //! 13 //! Invariants are encoded as ([`Aliasing`], [`Alignment`], [`Validity`]) 14 //! triples implementing the [`Invariants`] trait. 15 16 /// The invariants of a [`Ptr`][super::Ptr]. 17 pub trait Invariants: Sealed { 18 type Aliasing: Aliasing; 19 type Alignment: Alignment; 20 type Validity: Validity; 21 } 22 23 impl<A: Aliasing, AA: Alignment, V: Validity> Invariants for (A, AA, V) { 24 type Aliasing = A; 25 type Alignment = AA; 26 type Validity = V; 27 } 28 29 /// The aliasing invariant of a [`Ptr`][super::Ptr]. 30 /// 31 /// All aliasing invariants must permit reading from the bytes of a pointer's 32 /// referent which are not covered by [`UnsafeCell`]s. 33 /// 34 /// [`UnsafeCell`]: core::cell::UnsafeCell 35 pub trait Aliasing: Sealed { 36 /// Is `Self` [`Exclusive`]? 37 #[doc(hidden)] 38 const IS_EXCLUSIVE: bool; 39 } 40 41 /// The alignment invariant of a [`Ptr`][super::Ptr]. 42 pub trait Alignment: Sealed { 43 #[doc(hidden)] 44 #[must_use] 45 fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T 46 where 47 T: Copy + Read<I::Aliasing, R>, 48 I: Invariants<Alignment = Self, Validity = Valid>, 49 I::Aliasing: Reference; 50 } 51 52 /// The validity invariant of a [`Ptr`][super::Ptr]. 53 /// 54 /// # Safety 55 /// 56 /// In this section, we will use `Ptr<T, V>` as a shorthand for `Ptr<T, I: 57 /// Invariants<Validity = V>>` for brevity. 58 /// 59 /// Each `V: Validity` defines a set of bit values which may appear in the 60 /// referent of a `Ptr<T, V>`, denoted `S(T, V)`. Each `V: Validity`, in its 61 /// documentation, provides a definition of `S(T, V)` which must be valid for 62 /// all `T: ?Sized`. Any `V: Validity` must guarantee that this set is only a 63 /// function of the *bit validity* of the referent type, `T`, and not of any 64 /// other property of `T`. As a consequence, given `V: Validity`, `T`, and `U` 65 /// where `T` and `U` have the same bit validity, `S(V, T) = S(V, U)`. 66 /// 67 /// It is guaranteed that the referent of any `ptr: Ptr<T, V>` is a member of 68 /// `S(T, V)`. Unsafe code must ensure that this guarantee will be upheld for 69 /// any existing `Ptr`s or any `Ptr`s that that code creates. 70 /// 71 /// An important implication of this guarantee is that it restricts what 72 /// transmutes are sound, where "transmute" is used in this context to refer to 73 /// changing the referent type or validity invariant of a `Ptr`, as either 74 /// change may change the set of bit values permitted to appear in the referent. 75 /// In particular, the following are necessary (but not sufficient) conditions 76 /// in order for a transmute from `src: Ptr<T, V>` to `dst: Ptr<U, W>` to be 77 /// sound: 78 /// - If `S(T, V) = S(U, W)`, then no restrictions apply; otherwise, 79 /// - If `dst` permits mutation of its referent (e.g. via `Exclusive` aliasing 80 /// or interior mutation under `Shared` aliasing), then it must hold that 81 /// `S(T, V) ⊇ S(U, W)` - in other words, the transmute must not expand the 82 /// set of allowed referent bit patterns. A violation of this requirement 83 /// would permit using `dst` to write `x` where `x ∈ S(U, W)` but `x ∉ S(T, 84 /// V)`, which would violate the guarantee that `src`'s referent may only 85 /// contain values in `S(T, V)`. 86 /// - If the referent may be mutated without going through `dst` while `dst` is 87 /// live (e.g. via interior mutation on a `Shared`-aliased `Ptr` or `&` 88 /// reference), then it must hold that `S(T, V) ⊆ S(U, W)` - in other words, 89 /// the transmute must not shrink the set of allowed referent bit patterns. A 90 /// violation of this requirement would permit using `src` or another 91 /// mechanism (e.g. a `&` reference used to derive `src`) to write `x` where 92 /// `x ∈ S(T, V)` but `x ∉ S(U, W)`, which would violate the guarantee that 93 /// `dst`'s referent may only contain values in `S(U, W)`. 94 pub unsafe trait Validity: Sealed { 95 const KIND: ValidityKind; 96 } 97 98 pub enum ValidityKind { 99 Uninit, 100 AsInitialized, 101 Initialized, 102 Valid, 103 } 104 105 /// An [`Aliasing`] invariant which is either [`Shared`] or [`Exclusive`]. 106 /// 107 /// # Safety 108 /// 109 /// Given `A: Reference`, callers may assume that either `A = Shared` or `A = 110 /// Exclusive`. 111 pub trait Reference: Aliasing + Sealed {} 112 113 /// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a T`. 114 /// 115 /// The referent of a shared-aliased `Ptr` may be concurrently referenced by any 116 /// number of shared-aliased `Ptr` or `&T` references, or by any number of 117 /// `Ptr<U>` or `&U` references as permitted by `T`'s library safety invariants, 118 /// and may not be concurrently referenced by any exclusively-aliased `Ptr`s or 119 /// `&mut` references. The referent must not be mutated, except via 120 /// [`UnsafeCell`]s, and only when permitted by `T`'s library safety invariants. 121 /// 122 /// [`UnsafeCell`]: core::cell::UnsafeCell 123 pub enum Shared {} 124 impl Aliasing for Shared { 125 const IS_EXCLUSIVE: bool = false; 126 } 127 impl Reference for Shared {} 128 129 /// The `Ptr<'a, T>` adheres to the aliasing rules of a `&'a mut T`. 130 /// 131 /// The referent of an exclusively-aliased `Ptr` may not be concurrently 132 /// referenced by any other `Ptr`s or references, and may not be accessed (read 133 /// or written) other than via this `Ptr`. 134 pub enum Exclusive {} 135 impl Aliasing for Exclusive { 136 const IS_EXCLUSIVE: bool = true; 137 } 138 impl Reference for Exclusive {} 139 140 /// It is unknown whether the pointer is aligned. 141 pub enum Unaligned {} 142 143 impl Alignment for Unaligned { 144 #[inline(always)] 145 fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T 146 where 147 T: Copy + Read<I::Aliasing, R>, 148 I: Invariants<Alignment = Self, Validity = Valid>, 149 I::Aliasing: Reference, 150 { 151 (*ptr.into_unalign().as_ref()).into_inner() 152 } 153 } 154 155 /// The referent is aligned: for `Ptr<T>`, the referent's address is a multiple 156 /// of the `T`'s alignment. 157 pub enum Aligned {} 158 impl Alignment for Aligned { 159 #[inline(always)] 160 fn read<T, I, R>(ptr: crate::Ptr<'_, T, I>) -> T 161 where 162 T: Copy + Read<I::Aliasing, R>, 163 I: Invariants<Alignment = Self, Validity = Valid>, 164 I::Aliasing: Reference, 165 { 166 *ptr.as_ref() 167 } 168 } 169 170 /// Any bit pattern is allowed in the `Ptr`'s referent, including uninitialized 171 /// bytes. 172 pub enum Uninit {} 173 // SAFETY: `Uninit`'s validity is well-defined for all `T: ?Sized`, and is not a 174 // function of any property of `T` other than its bit validity (in fact, it's 175 // not even a property of `T`'s bit validity, but this is more than we are 176 // required to uphold). 177 unsafe impl Validity for Uninit { 178 const KIND: ValidityKind = ValidityKind::Uninit; 179 } 180 181 /// The byte ranges initialized in `T` are also initialized in the referent of a 182 /// `Ptr<T>`. 183 /// 184 /// Formally: uninitialized bytes may only be present in `Ptr<T>`'s referent 185 /// where they are guaranteed to be present in `T`. This is a dynamic property: 186 /// if, at a particular byte offset, a valid enum discriminant is set, the 187 /// subsequent bytes may only have uninitialized bytes as specified by the 188 /// corresponding enum. 189 /// 190 /// Formally, given `len = size_of_val_raw(ptr)`, at every byte offset, `b`, in 191 /// the range `[0, len)`: 192 /// - If, in any instance `t: T` of length `len`, the byte at offset `b` in `t` 193 /// is initialized, then the byte at offset `b` within `*ptr` must be 194 /// initialized. 195 /// - Let `c` be the contents of the byte range `[0, b)` in `*ptr`. Let `S` be 196 /// the subset of valid instances of `T` of length `len` which contain `c` in 197 /// the offset range `[0, b)`. If, in any instance of `t: T` in `S`, the byte 198 /// at offset `b` in `t` is initialized, then the byte at offset `b` in `*ptr` 199 /// must be initialized. 200 /// 201 /// Pragmatically, this means that if `*ptr` is guaranteed to contain an enum 202 /// type at a particular offset, and the enum discriminant stored in `*ptr` 203 /// corresponds to a valid variant of that enum type, then it is guaranteed 204 /// that the appropriate bytes of `*ptr` are initialized as defined by that 205 /// variant's bit validity (although note that the variant may contain another 206 /// enum type, in which case the same rules apply depending on the state of 207 /// its discriminant, and so on recursively). 208 pub enum AsInitialized {} 209 // SAFETY: `AsInitialized`'s validity is well-defined for all `T: ?Sized`, and 210 // is not a function of any property of `T` other than its bit validity. 211 unsafe impl Validity for AsInitialized { 212 const KIND: ValidityKind = ValidityKind::AsInitialized; 213 } 214 215 /// The byte ranges in the referent are fully initialized. In other words, if 216 /// the referent is `N` bytes long, then it contains a bit-valid `[u8; N]`. 217 pub enum Initialized {} 218 // SAFETY: `Initialized`'s validity is well-defined for all `T: ?Sized`, and is 219 // not a function of any property of `T` other than its bit validity (in fact, 220 // it's not even a property of `T`'s bit validity, but this is more than we are 221 // required to uphold). 222 unsafe impl Validity for Initialized { 223 const KIND: ValidityKind = ValidityKind::Initialized; 224 } 225 226 /// The referent of a `Ptr<T>` is valid for `T`, upholding bit validity and any 227 /// library safety invariants. 228 pub enum Valid {} 229 // SAFETY: `Valid`'s validity is well-defined for all `T: ?Sized`, and is not a 230 // function of any property of `T` other than its bit validity. 231 unsafe impl Validity for Valid { 232 const KIND: ValidityKind = ValidityKind::Valid; 233 } 234 235 /// # Safety 236 /// 237 /// `DT: CastableFrom<ST, SV, DV>` is sound if `SV = DV = Uninit` or `SV = DV = 238 /// Initialized`. 239 pub unsafe trait CastableFrom<ST: ?Sized, SV, DV> {} 240 241 // SAFETY: `SV = DV = Uninit`. 242 unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Uninit, Uninit> for DT {} 243 // SAFETY: `SV = DV = Initialized`. 244 unsafe impl<ST: ?Sized, DT: ?Sized> CastableFrom<ST, Initialized, Initialized> for DT {} 245 246 /// [`Ptr`](crate::Ptr) referents that permit unsynchronized read operations. 247 /// 248 /// `T: Read<A, R>` implies that a pointer to `T` with aliasing `A` permits 249 /// unsynchronized read operations. This can be because `A` is [`Exclusive`] or 250 /// because `T` does not permit interior mutation. 251 /// 252 /// # Safety 253 /// 254 /// `T: Read<A, R>` if either of the following conditions holds: 255 /// - `A` is [`Exclusive`] 256 /// - `T` implements [`Immutable`](crate::Immutable) 257 /// 258 /// As a consequence, if `T: Read<A, R>`, then any `Ptr<T, (A, ...)>` is 259 /// permitted to perform unsynchronized reads from its referent. 260 pub trait Read<A: Aliasing, R> {} 261 262 impl<A: Aliasing, T: ?Sized + crate::Immutable> Read<A, BecauseImmutable> for T {} 263 impl<T: ?Sized> Read<Exclusive, BecauseExclusive> for T {} 264 265 /// Unsynchronized reads are permitted because only one live [`Ptr`](crate::Ptr) 266 /// or reference may exist to the referent bytes at a time. 267 #[derive(Copy, Clone, Debug)] 268 pub enum BecauseExclusive {} 269 270 /// Unsynchronized reads are permitted because no live [`Ptr`](crate::Ptr)s or 271 /// references permit interior mutation. 272 #[derive(Copy, Clone, Debug)] 273 pub enum BecauseImmutable {} 274 275 use sealed::Sealed; 276 mod sealed { 277 use super::*; 278 279 pub trait Sealed {} 280 281 impl Sealed for Shared {} 282 impl Sealed for Exclusive {} 283 284 impl Sealed for Unaligned {} 285 impl Sealed for Aligned {} 286 287 impl Sealed for Uninit {} 288 impl Sealed for AsInitialized {} 289 impl Sealed for Initialized {} 290 impl Sealed for Valid {} 291 292 impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {} 293 294 impl Sealed for BecauseImmutable {} 295 impl Sealed for BecauseExclusive {} 296 } 297