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