1 // Copyright 2023 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 use core::{ 10 fmt::{Debug, Formatter}, 11 marker::PhantomData, 12 ptr::NonNull, 13 }; 14 15 use super::{inner::PtrInner, invariant::*}; 16 use crate::{ 17 util::{AlignmentVariance, Covariant, TransparentWrapper, ValidityVariance}, 18 AlignmentError, CastError, CastType, KnownLayout, SizeError, TryFromBytes, ValidityError, 19 }; 20 21 /// Module used to gate access to [`Ptr`]'s fields. 22 mod def { 23 use super::*; 24 25 #[cfg(doc)] 26 use super::super::invariant; 27 28 /// A raw pointer with more restrictions. 29 /// 30 /// `Ptr<T>` is similar to [`NonNull<T>`], but it is more restrictive in the 31 /// following ways (note that these requirements only hold of non-zero-sized 32 /// referents): 33 /// - It must derive from a valid allocation. 34 /// - It must reference a byte range which is contained inside the 35 /// allocation from which it derives. 36 /// - As a consequence, the byte range it references must have a size 37 /// which does not overflow `isize`. 38 /// 39 /// Depending on how `Ptr` is parameterized, it may have additional 40 /// invariants: 41 /// - `ptr` conforms to the aliasing invariant of 42 /// [`I::Aliasing`](invariant::Aliasing). 43 /// - `ptr` conforms to the alignment invariant of 44 /// [`I::Alignment`](invariant::Alignment). 45 /// - `ptr` conforms to the validity invariant of 46 /// [`I::Validity`](invariant::Validity). 47 /// 48 /// `Ptr<'a, T>` is [covariant] in `'a` and invariant in `T`. 49 /// 50 /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html 51 pub struct Ptr<'a, T, I> 52 where 53 T: ?Sized, 54 I: Invariants, 55 { 56 /// # Invariants 57 /// 58 /// 0. `ptr` conforms to the aliasing invariant of 59 /// [`I::Aliasing`](invariant::Aliasing). 60 /// 1. `ptr` conforms to the alignment invariant of 61 /// [`I::Alignment`](invariant::Alignment). 62 /// 2. `ptr` conforms to the validity invariant of 63 /// [`I::Validity`](invariant::Validity). 64 // SAFETY: `PtrInner<'a, T>` is covariant in `'a` and invariant in `T`. 65 ptr: PtrInner<'a, T>, 66 _invariants: PhantomData<I>, 67 } 68 69 impl<'a, T, I> Ptr<'a, T, I> 70 where 71 T: 'a + ?Sized, 72 I: Invariants, 73 { 74 /// Constructs a `Ptr` from a [`NonNull`]. 75 /// 76 /// # Safety 77 /// 78 /// The caller promises that: 79 /// 80 /// 0. If `ptr`'s referent is not zero sized, then `ptr` is derived from 81 /// some valid Rust allocation, `A`. 82 /// 1. If `ptr`'s referent is not zero sized, then `ptr` has valid 83 /// provenance for `A`. 84 /// 2. If `ptr`'s referent is not zero sized, then `ptr` addresses a 85 /// byte range which is entirely contained in `A`. 86 /// 3. `ptr` addresses a byte range whose length fits in an `isize`. 87 /// 4. `ptr` addresses a byte range which does not wrap around the 88 /// address space. 89 /// 5. If `ptr`'s referent is not zero sized, then `A` is guaranteed to 90 /// live for at least `'a`. 91 /// 6. `ptr` conforms to the aliasing invariant of 92 /// [`I::Aliasing`](invariant::Aliasing). 93 /// 7. `ptr` conforms to the alignment invariant of 94 /// [`I::Alignment`](invariant::Alignment). 95 /// 8. `ptr` conforms to the validity invariant of 96 /// [`I::Validity`](invariant::Validity). new(ptr: NonNull<T>) -> Ptr<'a, T, I>97 pub(super) unsafe fn new(ptr: NonNull<T>) -> Ptr<'a, T, I> { 98 // SAFETY: The caller has promised (in 0 - 5) to satisfy all safety 99 // invariants of `PtrInner::new`. 100 let ptr = unsafe { PtrInner::new(ptr) }; 101 // SAFETY: The caller has promised (in 6 - 8) to satisfy all safety 102 // invariants of `Ptr`. 103 Self { ptr, _invariants: PhantomData } 104 } 105 106 /// Constructs a new `Ptr` from a [`PtrInner`]. 107 /// 108 /// # Safety 109 /// 110 /// The caller promises that: 111 /// 112 /// 0. `ptr` conforms to the aliasing invariant of 113 /// [`I::Aliasing`](invariant::Aliasing). 114 /// 1. `ptr` conforms to the alignment invariant of 115 /// [`I::Alignment`](invariant::Alignment). 116 /// 2. `ptr` conforms to the validity invariant of 117 /// [`I::Validity`](invariant::Validity). from_inner(ptr: PtrInner<'a, T>) -> Ptr<'a, T, I>118 pub(super) unsafe fn from_inner(ptr: PtrInner<'a, T>) -> Ptr<'a, T, I> { 119 // SAFETY: The caller has promised to satisfy all safety invariants 120 // of `Ptr`. 121 Self { ptr, _invariants: PhantomData } 122 } 123 124 /// Converts this `Ptr<T>` to a [`PtrInner<T>`]. 125 /// 126 /// Note that this method does not consume `self`. The caller should 127 /// watch out for `unsafe` code which uses the returned value in a way 128 /// that violates the safety invariants of `self`. as_inner(&self) -> PtrInner<'a, T>129 pub(crate) fn as_inner(&self) -> PtrInner<'a, T> { 130 self.ptr 131 } 132 } 133 } 134 135 #[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain. 136 pub use def::Ptr; 137 138 /// External trait implementations on [`Ptr`]. 139 mod _external { 140 use super::*; 141 142 /// SAFETY: Shared pointers are safely `Copy`. `Ptr`'s other invariants 143 /// (besides aliasing) are unaffected by the number of references that exist 144 /// to `Ptr`'s referent. 145 impl<'a, T, I> Copy for Ptr<'a, T, I> 146 where 147 T: 'a + ?Sized, 148 I: Invariants<Aliasing = Shared>, 149 { 150 } 151 152 /// SAFETY: Shared pointers are safely `Clone`. `Ptr`'s other invariants 153 /// (besides aliasing) are unaffected by the number of references that exist 154 /// to `Ptr`'s referent. 155 impl<'a, T, I> Clone for Ptr<'a, T, I> 156 where 157 T: 'a + ?Sized, 158 I: Invariants<Aliasing = Shared>, 159 { 160 #[inline] clone(&self) -> Self161 fn clone(&self) -> Self { 162 *self 163 } 164 } 165 166 impl<'a, T, I> Debug for Ptr<'a, T, I> 167 where 168 T: 'a + ?Sized, 169 I: Invariants, 170 { 171 #[inline] fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result172 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { 173 self.as_inner().as_non_null().fmt(f) 174 } 175 } 176 } 177 178 /// Methods for converting to and from `Ptr` and Rust's safe reference types. 179 mod _conversions { 180 use super::*; 181 182 /// `&'a T` → `Ptr<'a, T>` 183 impl<'a, T> Ptr<'a, T, (Shared, Aligned, Valid)> 184 where 185 T: 'a + ?Sized, 186 { 187 /// Constructs a `Ptr` from a shared reference. 188 #[doc(hidden)] 189 #[inline] from_ref(ptr: &'a T) -> Self190 pub fn from_ref(ptr: &'a T) -> Self { 191 let inner = PtrInner::from_ref(ptr); 192 // SAFETY: 193 // 0. `ptr`, by invariant on `&'a T`, conforms to the aliasing 194 // invariant of `Shared`. 195 // 1. `ptr`, by invariant on `&'a T`, conforms to the alignment 196 // invariant of `Aligned`. 197 // 2. `ptr`, by invariant on `&'a T`, conforms to the validity 198 // invariant of `Valid`. 199 unsafe { Self::from_inner(inner) } 200 } 201 } 202 203 /// `&'a mut T` → `Ptr<'a, T>` 204 impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)> 205 where 206 T: 'a + ?Sized, 207 { 208 /// Constructs a `Ptr` from an exclusive reference. 209 #[inline] from_mut(ptr: &'a mut T) -> Self210 pub(crate) fn from_mut(ptr: &'a mut T) -> Self { 211 let inner = PtrInner::from_mut(ptr); 212 // SAFETY: 213 // 0. `ptr`, by invariant on `&'a mut T`, conforms to the aliasing 214 // invariant of `Exclusive`. 215 // 1. `ptr`, by invariant on `&'a mut T`, conforms to the alignment 216 // invariant of `Aligned`. 217 // 2. `ptr`, by invariant on `&'a mut T`, conforms to the validity 218 // invariant of `Valid`. 219 unsafe { Self::from_inner(inner) } 220 } 221 } 222 223 /// `Ptr<'a, T>` → `&'a T` 224 impl<'a, T, I> Ptr<'a, T, I> 225 where 226 T: 'a + ?Sized, 227 I: Invariants<Alignment = Aligned, Validity = Valid>, 228 I::Aliasing: Reference, 229 { 230 /// Converts `self` to a shared reference. 231 // This consumes `self`, not `&self`, because `self` is, logically, a 232 // pointer. For `I::Aliasing = invariant::Shared`, `Self: Copy`, and so 233 // this doesn't prevent the caller from still using the pointer after 234 // calling `as_ref`. 235 #[allow(clippy::wrong_self_convention)] as_ref(self) -> &'a T236 pub(crate) fn as_ref(self) -> &'a T { 237 let raw = self.as_inner().as_non_null(); 238 // SAFETY: This invocation of `NonNull::as_ref` satisfies its 239 // documented safety preconditions: 240 // 241 // 1. The pointer is properly aligned. This is ensured by-contract 242 // on `Ptr`, because the `I::Alignment` is `Aligned`. 243 // 244 // 2. If the pointer's referent is not zero-sized, then the pointer 245 // must be “dereferenceable” in the sense defined in the module 246 // documentation; i.e.: 247 // 248 // > The memory range of the given size starting at the pointer 249 // > must all be within the bounds of a single allocated object. 250 // > [2] 251 // 252 // This is ensured by contract on all `PtrInner`s. 253 // 254 // 3. The pointer must point to an initialized instance of `T`. This 255 // is ensured by-contract on `Ptr`, because the `I::Validity` is 256 // `Valid`. 257 // 258 // 4. You must enforce Rust’s aliasing rules. This is ensured by 259 // contract on `Ptr`, because `I::Aliasing: Reference`. Either it 260 // is `Shared` or `Exclusive`. If it is `Shared`, other 261 // references may not mutate the referent outside of 262 // `UnsafeCell`s. 263 // 264 // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_ref 265 // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety 266 unsafe { raw.as_ref() } 267 } 268 } 269 270 impl<'a, T, I> Ptr<'a, T, I> 271 where 272 T: 'a + ?Sized, 273 I: Invariants, 274 I::Aliasing: Reference, 275 { 276 /// Reborrows `self`, producing another `Ptr`. 277 /// 278 /// Since `self` is borrowed immutably, this prevents any mutable 279 /// methods from being called on `self` as long as the returned `Ptr` 280 /// exists. 281 #[doc(hidden)] 282 #[inline] 283 #[allow(clippy::needless_lifetimes)] // Allows us to name the lifetime in the safety comment below. reborrow<'b>(&'b mut self) -> Ptr<'b, T, I> where 'a: 'b,284 pub fn reborrow<'b>(&'b mut self) -> Ptr<'b, T, I> 285 where 286 'a: 'b, 287 { 288 // SAFETY: The following all hold by invariant on `self`, and thus 289 // hold of `ptr = self.as_inner()`: 290 // 0. SEE BELOW. 291 // 1. `ptr` conforms to the alignment invariant of 292 // [`I::Alignment`](invariant::Alignment). 293 // 2. `ptr` conforms to the validity invariant of 294 // [`I::Validity`](invariant::Validity). 295 // 296 // For aliasing (6 above), since `I::Aliasing: Reference`, 297 // there are two cases for `I::Aliasing`: 298 // - For `invariant::Shared`: `'a` outlives `'b`, and so the 299 // returned `Ptr` does not permit accessing the referent any 300 // longer than is possible via `self`. For shared aliasing, it is 301 // sound for multiple `Ptr`s to exist simultaneously which 302 // reference the same memory, so creating a new one is not 303 // problematic. 304 // - For `invariant::Exclusive`: Since `self` is `&'b mut` and we 305 // return a `Ptr` with lifetime `'b`, `self` is inaccessible to 306 // the caller for the lifetime `'b` - in other words, `self` is 307 // inaccessible to the caller as long as the returned `Ptr` 308 // exists. Since `self` is an exclusive `Ptr`, no other live 309 // references or `Ptr`s may exist which refer to the same memory 310 // while `self` is live. Thus, as long as the returned `Ptr` 311 // exists, no other references or `Ptr`s which refer to the same 312 // memory may be live. 313 unsafe { Ptr::from_inner(self.as_inner()) } 314 } 315 } 316 317 /// `Ptr<'a, T>` → `&'a mut T` 318 impl<'a, T> Ptr<'a, T, (Exclusive, Aligned, Valid)> 319 where 320 T: 'a + ?Sized, 321 { 322 /// Converts `self` to a mutable reference. 323 #[allow(clippy::wrong_self_convention)] as_mut(self) -> &'a mut T324 pub(crate) fn as_mut(self) -> &'a mut T { 325 let mut raw = self.as_inner().as_non_null(); 326 // SAFETY: This invocation of `NonNull::as_mut` satisfies its 327 // documented safety preconditions: 328 // 329 // 1. The pointer is properly aligned. This is ensured by-contract 330 // on `Ptr`, because the `ALIGNMENT_INVARIANT` is `Aligned`. 331 // 332 // 2. If the pointer's referent is not zero-sized, then the pointer 333 // must be “dereferenceable” in the sense defined in the module 334 // documentation; i.e.: 335 // 336 // > The memory range of the given size starting at the pointer 337 // > must all be within the bounds of a single allocated object. 338 // > [2] 339 // 340 // This is ensured by contract on all `PtrInner`s. 341 // 342 // 3. The pointer must point to an initialized instance of `T`. This 343 // is ensured by-contract on `Ptr`, because the validity 344 // invariant is `Valid`. 345 // 346 // 4. You must enforce Rust’s aliasing rules. This is ensured by 347 // contract on `Ptr`, because the `ALIASING_INVARIANT` is 348 // `Exclusive`. 349 // 350 // [1]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html#method.as_mut 351 // [2]: https://doc.rust-lang.org/std/ptr/index.html#safety 352 unsafe { raw.as_mut() } 353 } 354 } 355 356 /// `Ptr<'a, T = Wrapper<U>>` → `Ptr<'a, U>` 357 impl<'a, T, I> Ptr<'a, T, I> 358 where 359 T: 'a + TransparentWrapper<I, UnsafeCellVariance = Covariant> + ?Sized, 360 I: Invariants, 361 { 362 /// Converts `self` to a transparent wrapper type into a `Ptr` to the 363 /// wrapped inner type. transparent_wrapper_into_inner( self, ) -> Ptr< 'a, T::Inner, ( I::Aliasing, <T::AlignmentVariance as AlignmentVariance<I::Alignment>>::Applied, <T::ValidityVariance as ValidityVariance<I::Validity>>::Applied, ), >364 pub(crate) fn transparent_wrapper_into_inner( 365 self, 366 ) -> Ptr< 367 'a, 368 T::Inner, 369 ( 370 I::Aliasing, 371 <T::AlignmentVariance as AlignmentVariance<I::Alignment>>::Applied, 372 <T::ValidityVariance as ValidityVariance<I::Validity>>::Applied, 373 ), 374 > { 375 // SAFETY: 376 // - By invariant on `TransparentWrapper::cast_into_inner`: 377 // - This cast preserves address and referent size, and thus the 378 // returned pointer addresses the same bytes as `p` 379 // - This cast preserves provenance 380 // - By invariant on `TransparentWrapper<UnsafeCellVariance = 381 // Covariant>`, `T` and `T::Inner` have `UnsafeCell`s at the same 382 // byte ranges. Since `p` and the returned pointer address the 383 // same byte range, they refer to `UnsafeCell`s at the same byte 384 // ranges. 385 // - By invariant on `TransparentWrapper`, since `self` satisfies 386 // the validity invariant `I::Validity`, the returned pointer (of 387 // type `T::Inner`) satisfies the given "applied" validity 388 // invariant. 389 let ptr = unsafe { self.transmute_unchecked(|p| T::cast_into_inner(p)) }; 390 // SAFETY: By invariant on `TransparentWrapper`, since `self` 391 // satisfies the alignment invariant `I::Alignment`, the returned 392 // pointer (of type `T::Inner`) satisfies the given "applied" 393 // alignment invariant. 394 unsafe { ptr.assume_alignment() } 395 } 396 } 397 398 /// `Ptr<'a, T>` → `Ptr<'a, U>` 399 impl<'a, T: ?Sized, I> Ptr<'a, T, I> 400 where 401 I: Invariants, 402 { 403 /// Casts to a different (unsized) target type without checking interior 404 /// mutability. 405 /// 406 /// Callers should prefer [`cast_unsized`] where possible. 407 /// 408 /// [`cast_unsized`]: Ptr::cast_unsized 409 /// 410 /// # Safety 411 /// 412 /// The caller promises that `u = cast(p)` is a pointer cast with the 413 /// following properties: 414 /// - `u` addresses a subset of the bytes addressed by `p` 415 /// - `u` has the same provenance as `p` 416 /// - If `I::Aliasing` is [`Shared`], `UnsafeCell`s in `*u` must exist 417 /// at ranges identical to those at which `UnsafeCell`s exist in `*p` 418 /// - It is sound to transmute a pointer of type `T` with aliasing 419 /// `I::Aliasing` and validity `I::Validity` to a pointer of type `U` 420 /// with aliasing `I::Aliasing` and validity `V`. This is a subtle 421 /// soundness requirement that is a function of `T`, `U`, 422 /// `I::Aliasing`, `I::Validity`, and `V`, and may depend upon the 423 /// presence, absence, or specific location of `UnsafeCell`s in `T` 424 /// and/or `U`. 425 #[doc(hidden)] 426 #[inline] transmute_unchecked<U: ?Sized, V, F>( self, cast: F, ) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)> where V: Validity, F: FnOnce(*mut T) -> *mut U,427 pub unsafe fn transmute_unchecked<U: ?Sized, V, F>( 428 self, 429 cast: F, 430 ) -> Ptr<'a, U, (I::Aliasing, Unaligned, V)> 431 where 432 V: Validity, 433 F: FnOnce(*mut T) -> *mut U, 434 { 435 let ptr = cast(self.as_inner().as_non_null().as_ptr()); 436 437 // SAFETY: Caller promises that `cast` returns a pointer whose 438 // address is in the range of `self.as_inner().as_non_null()`'s referent. By 439 // invariant, none of these addresses are null. 440 let ptr = unsafe { NonNull::new_unchecked(ptr) }; 441 442 // SAFETY: 443 // 444 // Lemma 1: `ptr` has the same provenance as `self`. The caller 445 // promises that `cast` preserves provenance, and we call it with 446 // `self.as_inner().as_non_null()`. 447 // 448 // 0. By invariant, if `self`'s referent is not zero sized, then 449 // `self` is derived from some valid Rust allocation, `A`. By 450 // Lemma 1, `ptr` has the same provenance as `self`. Thus, `ptr` 451 // is derived from `A`. 452 // 1. By invariant, if `self`'s referent is not zero sized, then 453 // `self` has valid provenance for `A`. By Lemma 1, so does 454 // `ptr`. 455 // 2. By invariant on `self` and caller precondition, if `ptr`'s 456 // referent is not zero sized, then `ptr` addresses a byte range 457 // which is entirely contained in `A`. 458 // 3. By invariant on `self` and caller precondition, `ptr` 459 // addresses a byte range whose length fits in an `isize`. 460 // 4. By invariant on `self` and caller precondition, `ptr` 461 // addresses a byte range which does not wrap around the address 462 // space. 463 // 5. By invariant on `self`, if `self`'s referent is not zero 464 // sized, then `A` is guaranteed to live for at least `'a`. 465 // 6. `ptr` conforms to the aliasing invariant of `I::Aliasing`: 466 // - `Exclusive`: `self` is the only `Ptr` or reference which is 467 // permitted to read or modify the referent for the lifetime 468 // `'a`. Since we consume `self` by value, the returned pointer 469 // remains the only `Ptr` or reference which is permitted to 470 // read or modify the referent for the lifetime `'a`. 471 // - `Shared`: Since `self` has aliasing `Shared`, we know that 472 // no other code may mutate the referent during the lifetime 473 // `'a`, except via `UnsafeCell`s. The caller promises that 474 // `UnsafeCell`s cover the same byte ranges in `*self` and 475 // `*ptr`. For each byte in the referent, there are two cases: 476 // - If the byte is not covered by an `UnsafeCell` in `*ptr`, 477 // then it is not covered in `*self`. By invariant on `self`, 478 // it will not be mutated during `'a`, as required by the 479 // constructed pointer. Similarly, the returned pointer will 480 // not permit any mutations to these locations, as required 481 // by the invariant on `self`. 482 // - If the byte is covered by an `UnsafeCell` in `*ptr`, then 483 // the returned pointer's invariants do not assume that the 484 // byte will not be mutated during `'a`. While the returned 485 // pointer will permit mutation of this byte during `'a`, by 486 // invariant on `self`, no other code assumes that this will 487 // not happen. 488 // - `Inaccessible`: There are no restrictions we need to uphold. 489 // 7. `ptr` trivially satisfies the alignment invariant `Unaligned`. 490 // 8. The caller promises that `ptr` conforms to the validity 491 // invariant `V` with respect to its referent type, `U`. 492 unsafe { Ptr::new(ptr) } 493 } 494 } 495 496 /// `Ptr<'a, T, (_, _, _)>` → `Ptr<'a, Unalign<T>, (_, Aligned, _)>` 497 impl<'a, T, I> Ptr<'a, T, I> 498 where 499 I: Invariants, 500 { 501 /// Converts a `Ptr` an unaligned `T` into a `Ptr` to an aligned 502 /// `Unalign<T>`. into_unalign( self, ) -> Ptr<'a, crate::Unalign<T>, (I::Aliasing, Aligned, I::Validity)>503 pub(crate) fn into_unalign( 504 self, 505 ) -> Ptr<'a, crate::Unalign<T>, (I::Aliasing, Aligned, I::Validity)> { 506 // SAFETY: 507 // - This cast preserves provenance. 508 // - This cast preserves address. `Unalign<T>` promises to have the 509 // same size as `T`, and so the cast returns a pointer addressing 510 // the same byte range as `p`. 511 // - By the same argument, the returned pointer refers to 512 // `UnsafeCell`s at the same locations as `p`. 513 // - `Unalign<T>` promises to have the same bit validity as `T` 514 let ptr = unsafe { 515 #[allow(clippy::as_conversions)] 516 self.transmute_unchecked(|p: *mut T| p as *mut crate::Unalign<T>) 517 }; 518 ptr.bikeshed_recall_aligned() 519 } 520 } 521 } 522 523 /// State transitions between invariants. 524 mod _transitions { 525 use super::*; 526 527 impl<'a, T, I> Ptr<'a, T, I> 528 where 529 T: 'a + ?Sized, 530 I: Invariants, 531 { 532 /// Returns a `Ptr` with [`Exclusive`] aliasing if `self` already has 533 /// `Exclusive` aliasing, or generates a compile-time assertion failure. 534 /// 535 /// This allows code which is generic over aliasing to down-cast to a 536 /// concrete aliasing. 537 /// 538 /// [`Exclusive`]: crate::pointer::invariant::Exclusive 539 #[inline] into_exclusive_or_pme( self, ) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)>540 pub(crate) fn into_exclusive_or_pme( 541 self, 542 ) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)> { 543 // NOTE(https://github.com/rust-lang/rust/issues/131625): We do this 544 // rather than just having `Aliasing::IS_EXCLUSIVE` have the panic 545 // behavior because doing it that way causes rustdoc to fail while 546 // attempting to document hidden items (since it evaluates the 547 // constant - and thus panics). 548 trait AliasingExt: Aliasing { 549 const IS_EXCL: bool; 550 } 551 552 impl<A: Aliasing> AliasingExt for A { 553 const IS_EXCL: bool = { 554 const_assert!(Self::IS_EXCLUSIVE); 555 true 556 }; 557 } 558 559 assert!(I::Aliasing::IS_EXCL); 560 561 // SAFETY: We've confirmed that `self` already has the aliasing 562 // `Exclusive`. If it didn't, either the preceding assert would fail 563 // or evaluating `I::Aliasing::IS_EXCL` would fail. We're *pretty* 564 // sure that it's guaranteed to fail const eval, but the `assert!` 565 // provides a backstop in case that doesn't work. 566 unsafe { self.assume_exclusive() } 567 } 568 569 /// Assumes that `self` satisfies the invariants `H`. 570 /// 571 /// # Safety 572 /// 573 /// The caller promises that `self` satisfies the invariants `H`. assume_invariants<H: Invariants>(self) -> Ptr<'a, T, H>574 unsafe fn assume_invariants<H: Invariants>(self) -> Ptr<'a, T, H> { 575 // SAFETY: The caller has promised to satisfy all parameterized 576 // invariants of `Ptr`. `Ptr`'s other invariants are satisfied 577 // by-contract by the source `Ptr`. 578 unsafe { Ptr::from_inner(self.as_inner()) } 579 } 580 581 /// Helps the type system unify two distinct invariant types which are 582 /// actually the same. unify_invariants< H: Invariants<Aliasing = I::Aliasing, Alignment = I::Alignment, Validity = I::Validity>, >( self, ) -> Ptr<'a, T, H>583 pub(crate) fn unify_invariants< 584 H: Invariants<Aliasing = I::Aliasing, Alignment = I::Alignment, Validity = I::Validity>, 585 >( 586 self, 587 ) -> Ptr<'a, T, H> { 588 // SAFETY: The associated type bounds on `H` ensure that the 589 // invariants are unchanged. 590 unsafe { self.assume_invariants::<H>() } 591 } 592 593 /// Assumes that `self` satisfies the aliasing requirement of `A`. 594 /// 595 /// # Safety 596 /// 597 /// The caller promises that `self` satisfies the aliasing requirement 598 /// of `A`. 599 #[inline] assume_aliasing<A: Aliasing>( self, ) -> Ptr<'a, T, (A, I::Alignment, I::Validity)>600 pub(crate) unsafe fn assume_aliasing<A: Aliasing>( 601 self, 602 ) -> Ptr<'a, T, (A, I::Alignment, I::Validity)> { 603 // SAFETY: The caller promises that `self` satisfies the aliasing 604 // requirements of `A`. 605 unsafe { self.assume_invariants() } 606 } 607 608 /// Assumes `self` satisfies the aliasing requirement of [`Exclusive`]. 609 /// 610 /// # Safety 611 /// 612 /// The caller promises that `self` satisfies the aliasing requirement 613 /// of `Exclusive`. 614 /// 615 /// [`Exclusive`]: crate::pointer::invariant::Exclusive 616 #[inline] assume_exclusive( self, ) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)>617 pub(crate) unsafe fn assume_exclusive( 618 self, 619 ) -> Ptr<'a, T, (Exclusive, I::Alignment, I::Validity)> { 620 // SAFETY: The caller promises that `self` satisfies the aliasing 621 // requirements of `Exclusive`. 622 unsafe { self.assume_aliasing::<Exclusive>() } 623 } 624 625 /// Assumes that `self`'s referent is validly-aligned for `T` if 626 /// required by `A`. 627 /// 628 /// # Safety 629 /// 630 /// The caller promises that `self`'s referent conforms to the alignment 631 /// invariant of `T` if required by `A`. 632 #[inline] assume_alignment<A: Alignment>( self, ) -> Ptr<'a, T, (I::Aliasing, A, I::Validity)>633 pub(crate) unsafe fn assume_alignment<A: Alignment>( 634 self, 635 ) -> Ptr<'a, T, (I::Aliasing, A, I::Validity)> { 636 // SAFETY: The caller promises that `self`'s referent is 637 // well-aligned for `T` if required by `A` . 638 unsafe { self.assume_invariants() } 639 } 640 641 /// Checks the `self`'s alignment at runtime, returning an aligned `Ptr` 642 /// on success. bikeshed_try_into_aligned( self, ) -> Result<Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)>, AlignmentError<Self, T>> where T: Sized,643 pub(crate) fn bikeshed_try_into_aligned( 644 self, 645 ) -> Result<Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)>, AlignmentError<Self, T>> 646 where 647 T: Sized, 648 { 649 if let Err(err) = 650 crate::util::validate_aligned_to::<_, T>(self.as_inner().as_non_null()) 651 { 652 return Err(err.with_src(self)); 653 } 654 655 // SAFETY: We just checked the alignment. 656 Ok(unsafe { self.assume_alignment::<Aligned>() }) 657 } 658 659 /// Recalls that `self`'s referent is validly-aligned for `T`. 660 #[inline] 661 // TODO(#859): Reconsider the name of this method before making it 662 // public. bikeshed_recall_aligned( self, ) -> Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)> where T: crate::Unaligned,663 pub(crate) fn bikeshed_recall_aligned( 664 self, 665 ) -> Ptr<'a, T, (I::Aliasing, Aligned, I::Validity)> 666 where 667 T: crate::Unaligned, 668 { 669 // SAFETY: The bound `T: Unaligned` ensures that `T` has no 670 // non-trivial alignment requirement. 671 unsafe { self.assume_alignment::<Aligned>() } 672 } 673 674 /// Assumes that `self`'s referent conforms to the validity requirement 675 /// of `V`. 676 /// 677 /// # Safety 678 /// 679 /// The caller promises that `self`'s referent conforms to the validity 680 /// requirement of `V`. 681 #[doc(hidden)] 682 #[must_use] 683 #[inline] assume_validity<V: Validity>( self, ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, V)>684 pub unsafe fn assume_validity<V: Validity>( 685 self, 686 ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, V)> { 687 // SAFETY: The caller promises that `self`'s referent conforms to 688 // the validity requirement of `V`. 689 unsafe { self.assume_invariants() } 690 } 691 692 /// A shorthand for `self.assume_validity<invariant::Initialized>()`. 693 /// 694 /// # Safety 695 /// 696 /// The caller promises to uphold the safety preconditions of 697 /// `self.assume_validity<invariant::Initialized>()`. 698 #[doc(hidden)] 699 #[must_use] 700 #[inline] assume_initialized( self, ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Initialized)>701 pub unsafe fn assume_initialized( 702 self, 703 ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Initialized)> { 704 // SAFETY: The caller has promised to uphold the safety 705 // preconditions. 706 unsafe { self.assume_validity::<Initialized>() } 707 } 708 709 /// A shorthand for `self.assume_validity<Valid>()`. 710 /// 711 /// # Safety 712 /// 713 /// The caller promises to uphold the safety preconditions of 714 /// `self.assume_validity<Valid>()`. 715 #[doc(hidden)] 716 #[must_use] 717 #[inline] assume_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)>718 pub unsafe fn assume_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)> { 719 // SAFETY: The caller has promised to uphold the safety 720 // preconditions. 721 unsafe { self.assume_validity::<Valid>() } 722 } 723 724 /// Recalls that `self`'s referent is initialized. 725 #[doc(hidden)] 726 #[must_use] 727 #[inline] 728 // TODO(#859): Reconsider the name of this method before making it 729 // public. bikeshed_recall_initialized_from_bytes( self, ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Initialized)> where T: crate::IntoBytes + crate::FromBytes, I: Invariants<Validity = Valid>,730 pub fn bikeshed_recall_initialized_from_bytes( 731 self, 732 ) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Initialized)> 733 where 734 T: crate::IntoBytes + crate::FromBytes, 735 I: Invariants<Validity = Valid>, 736 { 737 // SAFETY: The `T: IntoBytes` bound ensures that any bit-valid `T` 738 // is entirely initialized. `I: Invariants<Validity = Valid>` 739 // ensures that `self`'s referent is a bit-valid `T`. Producing an 740 // `Initialized` `Ptr` may permit the caller to write arbitrary 741 // initialized bytes to the referent (depending on aliasing mode and 742 // presence of `UnsafeCell`s). `T: FromBytes` ensures that any byte 743 // sequence written will remain a bit-valid `T`. 744 unsafe { self.assume_initialized() } 745 } 746 747 /// Recalls that `self`'s referent is initialized. 748 #[doc(hidden)] 749 #[must_use] 750 #[inline] 751 // TODO(#859): Reconsider the name of this method before making it 752 // public. bikeshed_recall_initialized_immutable( self, ) -> Ptr<'a, T, (Shared, I::Alignment, Initialized)> where T: crate::IntoBytes + crate::Immutable, I: Invariants<Aliasing = Shared, Validity = Valid>,753 pub fn bikeshed_recall_initialized_immutable( 754 self, 755 ) -> Ptr<'a, T, (Shared, I::Alignment, Initialized)> 756 where 757 T: crate::IntoBytes + crate::Immutable, 758 I: Invariants<Aliasing = Shared, Validity = Valid>, 759 { 760 // SAFETY: The `T: IntoBytes` bound ensures that any bit-valid `T` 761 // is entirely initialized. `I: Invariants<Validity = Valid>` 762 // ensures that `self`'s referent is a bit-valid `T`. Since `T: 763 // Immutable` and the aliasing is `Shared`, the resulting `Ptr` 764 // cannot be used to modify the referent, and so it's acceptable 765 // that going from `Valid` to `Initialized` may increase the set of 766 // values allowed in the referent. 767 unsafe { self.assume_initialized() } 768 } 769 770 /// Recalls that `self`'s referent is bit-valid for `T`. 771 #[doc(hidden)] 772 #[must_use] 773 #[inline] 774 // TODO(#859): Reconsider the name of this method before making it 775 // public. bikeshed_recall_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)> where T: crate::FromBytes, I: Invariants<Validity = Initialized>,776 pub fn bikeshed_recall_valid(self) -> Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)> 777 where 778 T: crate::FromBytes, 779 I: Invariants<Validity = Initialized>, 780 { 781 // SAFETY: The bound `T: FromBytes` ensures that any initialized 782 // sequence of bytes is bit-valid for `T`. `I: Invariants<Validity = 783 // invariant::Initialized>` ensures that all of the referent bytes 784 // are initialized. 785 unsafe { self.assume_valid() } 786 } 787 788 /// Checks that `self`'s referent is validly initialized for `T`, 789 /// returning a `Ptr` with `Valid` on success. 790 /// 791 /// # Panics 792 /// 793 /// This method will panic if 794 /// [`T::is_bit_valid`][TryFromBytes::is_bit_valid] panics. 795 /// 796 /// # Safety 797 /// 798 /// On error, unsafe code may rely on this method's returned 799 /// `ValidityError` containing `self`. 800 #[inline] try_into_valid<R>( mut self, ) -> Result<Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)>, ValidityError<Self, T>> where T: TryFromBytes + Read<I::Aliasing, R>, I::Aliasing: Reference, I: Invariants<Validity = Initialized>,801 pub(crate) fn try_into_valid<R>( 802 mut self, 803 ) -> Result<Ptr<'a, T, (I::Aliasing, I::Alignment, Valid)>, ValidityError<Self, T>> 804 where 805 T: TryFromBytes + Read<I::Aliasing, R>, 806 I::Aliasing: Reference, 807 I: Invariants<Validity = Initialized>, 808 { 809 // This call may panic. If that happens, it doesn't cause any soundness 810 // issues, as we have not generated any invalid state which we need to 811 // fix before returning. 812 if T::is_bit_valid(self.reborrow().forget_aligned()) { 813 // SAFETY: If `T::is_bit_valid`, code may assume that `self` 814 // contains a bit-valid instance of `Self`. 815 Ok(unsafe { self.assume_valid() }) 816 } else { 817 Err(ValidityError::new(self)) 818 } 819 } 820 821 /// Forgets that `self`'s referent is validly-aligned for `T`. 822 #[doc(hidden)] 823 #[must_use] 824 #[inline] forget_aligned(self) -> Ptr<'a, T, (I::Aliasing, Unaligned, I::Validity)>825 pub fn forget_aligned(self) -> Ptr<'a, T, (I::Aliasing, Unaligned, I::Validity)> { 826 // SAFETY: `Unaligned` is less restrictive than `Aligned`. 827 unsafe { self.assume_invariants() } 828 } 829 } 830 } 831 832 /// Casts of the referent type. 833 mod _casts { 834 use super::*; 835 836 impl<'a, T, I> Ptr<'a, T, I> 837 where 838 T: 'a + ?Sized, 839 I: Invariants, 840 { 841 /// Casts to a different (unsized) target type without checking interior 842 /// mutability. 843 /// 844 /// Callers should prefer [`cast_unsized`] where possible. 845 /// 846 /// [`cast_unsized`]: Ptr::cast_unsized 847 /// 848 /// # Safety 849 /// 850 /// The caller promises that `u = cast(p)` is a pointer cast with the 851 /// following properties: 852 /// - `u` addresses a subset of the bytes addressed by `p` 853 /// - `u` has the same provenance as `p` 854 /// - If `I::Aliasing` is [`Shared`], `UnsafeCell`s in `*u` must exist 855 /// at ranges identical to those at which `UnsafeCell`s exist in `*p` 856 #[doc(hidden)] 857 #[inline] cast_unsized_unchecked<U, F: FnOnce(*mut T) -> *mut U>( self, cast: F, ) -> Ptr<'a, U, (I::Aliasing, Unaligned, I::Validity)> where U: 'a + CastableFrom<T, I::Validity, I::Validity> + ?Sized,858 pub unsafe fn cast_unsized_unchecked<U, F: FnOnce(*mut T) -> *mut U>( 859 self, 860 cast: F, 861 ) -> Ptr<'a, U, (I::Aliasing, Unaligned, I::Validity)> 862 where 863 U: 'a + CastableFrom<T, I::Validity, I::Validity> + ?Sized, 864 { 865 // SAFETY: 866 // - The caller promises that `u = cast(p)` is a pointer which 867 // satisfies: 868 // - `u` addresses a subset of the bytes addressed by `p` 869 // - `u` has the same provenance as `p` 870 // - If `I::Aliasing` is [`Shared`], `UnsafeCell`s in `*u` must 871 // exist at ranges identical to those at which `UnsafeCell`s 872 // exist in `*p` 873 // - By `U: CastableFrom<T, I::Validity, I::Validity>`, 874 // `I::Validity` is either `Uninit` or `Initialized`. In both 875 // cases, the bit validity `I::Validity` has the same semantics 876 // regardless of referent type. In other words, the set of allowed 877 // referent values for `Ptr<T, (_, _, I::Validity)>` and `Ptr<U, 878 // (_, _, I::Validity)>` are identical. 879 unsafe { self.transmute_unchecked(cast) } 880 } 881 882 /// Casts to a different (unsized) target type. 883 /// 884 /// # Safety 885 /// 886 /// The caller promises that `u = cast(p)` is a pointer cast with the 887 /// following properties: 888 /// - `u` addresses a subset of the bytes addressed by `p` 889 /// - `u` has the same provenance as `p` 890 #[doc(hidden)] 891 #[inline] cast_unsized<U, F, R, S>( self, cast: F, ) -> Ptr<'a, U, (I::Aliasing, Unaligned, I::Validity)> where T: Read<I::Aliasing, R>, U: 'a + ?Sized + Read<I::Aliasing, S> + CastableFrom<T, I::Validity, I::Validity>, F: FnOnce(*mut T) -> *mut U,892 pub unsafe fn cast_unsized<U, F, R, S>( 893 self, 894 cast: F, 895 ) -> Ptr<'a, U, (I::Aliasing, Unaligned, I::Validity)> 896 where 897 T: Read<I::Aliasing, R>, 898 U: 'a + ?Sized + Read<I::Aliasing, S> + CastableFrom<T, I::Validity, I::Validity>, 899 F: FnOnce(*mut T) -> *mut U, 900 { 901 // SAFETY: Because `T` and `U` both implement `Read<I::Aliasing, _>`, 902 // either: 903 // - `I::Aliasing` is `Exclusive` 904 // - `T` and `U` are both `Immutable`, in which case they trivially 905 // contain `UnsafeCell`s at identical locations 906 // 907 // The caller promises all other safety preconditions. 908 unsafe { self.cast_unsized_unchecked(cast) } 909 } 910 } 911 912 impl<'a, T, I> Ptr<'a, T, I> 913 where 914 T: 'a + KnownLayout + ?Sized, 915 I: Invariants<Validity = Initialized>, 916 { 917 /// Casts this pointer-to-initialized into a pointer-to-bytes. 918 #[allow(clippy::wrong_self_convention)] as_bytes<R>(self) -> Ptr<'a, [u8], (I::Aliasing, Aligned, Valid)> where T: Read<I::Aliasing, R>, I::Aliasing: Reference,919 pub(crate) fn as_bytes<R>(self) -> Ptr<'a, [u8], (I::Aliasing, Aligned, Valid)> 920 where 921 T: Read<I::Aliasing, R>, 922 I::Aliasing: Reference, 923 { 924 let bytes = match T::size_of_val_raw(self.as_inner().as_non_null()) { 925 Some(bytes) => bytes, 926 // SAFETY: `KnownLayout::size_of_val_raw` promises to always 927 // return `Some` so long as the resulting size fits in a 928 // `usize`. By invariant on `Ptr`, `self` refers to a range of 929 // bytes whose size fits in an `isize`, which implies that it 930 // also fits in a `usize`. 931 None => unsafe { core::hint::unreachable_unchecked() }, 932 }; 933 934 // SAFETY: 935 // - `slice_from_raw_parts_mut` and `.cast` both preserve the 936 // pointer's address, and `bytes` is the length of `p`, so the 937 // returned pointer addresses the same bytes as `p` 938 // - `slice_from_raw_parts_mut` and `.cast` both preserve provenance 939 let ptr: Ptr<'a, [u8], _> = unsafe { 940 self.cast_unsized(|p: *mut T| { 941 #[allow(clippy::as_conversions)] 942 core::ptr::slice_from_raw_parts_mut(p.cast::<u8>(), bytes) 943 }) 944 }; 945 946 let ptr = ptr.bikeshed_recall_aligned(); 947 948 // SAFETY: `ptr`'s referent begins as `Initialized`, denoting that 949 // all bytes of the referent are initialized bytes. The referent 950 // type is then casted to `[u8]`, whose only validity invariant is 951 // that its bytes are initialized. This validity invariant is 952 // satisfied by the `Initialized` invariant on the starting `ptr`. 953 unsafe { ptr.assume_validity::<Valid>() } 954 } 955 } 956 957 impl<'a, T, I, const N: usize> Ptr<'a, [T; N], I> 958 where 959 T: 'a, 960 I: Invariants, 961 { 962 /// Casts this pointer-to-array into a slice. 963 #[allow(clippy::wrong_self_convention)] as_slice(self) -> Ptr<'a, [T], I>964 pub(crate) fn as_slice(self) -> Ptr<'a, [T], I> { 965 let slice = self.as_inner().as_slice(); 966 // SAFETY: Note that, by post-condition on `PtrInner::as_slice`, 967 // `slice` refers to the same byte range as `self.as_inner()`. 968 // 969 // 6. Thus, `slice` conforms to the aliasing invariant of 970 // `I::Aliasing` because `self` does. 971 // 7. By the above lemma, `slice` conforms to the alignment 972 // invariant of `I::Alignment` because `self` does. 973 // 8. By the above lemma, `slice` conforms to the validity invariant 974 // of `I::Validity` because `self` does. 975 unsafe { Ptr::from_inner(slice) } 976 } 977 } 978 979 /// For caller convenience, these methods are generic over alignment 980 /// invariant. In practice, the referent is always well-aligned, because the 981 /// alignment of `[u8]` is 1. 982 impl<'a, I> Ptr<'a, [u8], I> 983 where 984 I: Invariants<Validity = Valid>, 985 { 986 /// Attempts to cast `self` to a `U` using the given cast type. 987 /// 988 /// If `U` is a slice DST and pointer metadata (`meta`) is provided, 989 /// then the cast will only succeed if it would produce an object with 990 /// the given metadata. 991 /// 992 /// Returns `None` if the resulting `U` would be invalidly-aligned, if 993 /// no `U` can fit in `self`, or if the provided pointer metadata 994 /// describes an invalid instance of `U`. On success, returns a pointer 995 /// to the largest-possible `U` which fits in `self`. 996 /// 997 /// # Safety 998 /// 999 /// The caller may assume that this implementation is correct, and may 1000 /// rely on that assumption for the soundness of their code. In 1001 /// particular, the caller may assume that, if `try_cast_into` returns 1002 /// `Some((ptr, remainder))`, then `ptr` and `remainder` refer to 1003 /// non-overlapping byte ranges within `self`, and that `ptr` and 1004 /// `remainder` entirely cover `self`. Finally: 1005 /// - If this is a prefix cast, `ptr` has the same address as `self`. 1006 /// - If this is a suffix cast, `remainder` has the same address as 1007 /// `self`. 1008 #[inline(always)] try_cast_into<U, R>( self, cast_type: CastType, meta: Option<U::PointerMetadata>, ) -> Result< (Ptr<'a, U, (I::Aliasing, Aligned, Initialized)>, Ptr<'a, [u8], I>), CastError<Self, U>, > where I::Aliasing: Reference, U: 'a + ?Sized + KnownLayout + Read<I::Aliasing, R>,1009 pub(crate) fn try_cast_into<U, R>( 1010 self, 1011 cast_type: CastType, 1012 meta: Option<U::PointerMetadata>, 1013 ) -> Result< 1014 (Ptr<'a, U, (I::Aliasing, Aligned, Initialized)>, Ptr<'a, [u8], I>), 1015 CastError<Self, U>, 1016 > 1017 where 1018 I::Aliasing: Reference, 1019 U: 'a + ?Sized + KnownLayout + Read<I::Aliasing, R>, 1020 { 1021 let (inner, remainder) = 1022 self.as_inner().try_cast_into(cast_type, meta).map_err(|err| { 1023 err.map_src(|inner| 1024 // SAFETY: `PtrInner::try_cast_into` promises to return its 1025 // original argument on error, which was originally produced 1026 // by `self.as_inner()`, which is guaranteed to satisfy 1027 // `Ptr`'s invariants. 1028 unsafe { Ptr::from_inner(inner) }) 1029 })?; 1030 1031 // SAFETY: 1032 // 0. Since `U: Read<I::Aliasing, _>`, either: 1033 // - `I::Aliasing` is `Exclusive`, in which case both `src` and 1034 // `ptr` conform to `Exclusive` 1035 // - `I::Aliasing` is `Shared` and `U` is `Immutable` (we already 1036 // know that `[u8]: Immutable`). In this case, neither `U` nor 1037 // `[u8]` permit mutation, and so `Shared` aliasing is 1038 // satisfied. 1039 // 1. `ptr` conforms to the alignment invariant of `Aligned` because 1040 // it is derived from `try_cast_into`, which promises that the 1041 // object described by `target` is validly aligned for `U`. 1042 // 2. By trait bound, `self` - and thus `target` - is a bit-valid 1043 // `[u8]`. All bit-valid `[u8]`s have all of their bytes 1044 // initialized, so `ptr` conforms to the validity invariant of 1045 // `Initialized`. 1046 let res = unsafe { Ptr::from_inner(inner) }; 1047 1048 // SAFETY: 1049 // 0. `self` and `remainder` both have the type `[u8]`. Thus, they 1050 // have `UnsafeCell`s at the same locations. Type casting does 1051 // not affect aliasing. 1052 // 1. `[u8]` has no alignment requirement. 1053 // 2. `self` has validity `Valid` and has type `[u8]`. Since 1054 // `remainder` references a subset of `self`'s referent, it is 1055 // also bit-valid. 1056 let remainder = unsafe { Ptr::from_inner(remainder) }; 1057 1058 Ok((res, remainder)) 1059 } 1060 1061 /// Attempts to cast `self` into a `U`, failing if all of the bytes of 1062 /// `self` cannot be treated as a `U`. 1063 /// 1064 /// In particular, this method fails if `self` is not validly-aligned 1065 /// for `U` or if `self`'s size is not a valid size for `U`. 1066 /// 1067 /// # Safety 1068 /// 1069 /// On success, the caller may assume that the returned pointer 1070 /// references the same byte range as `self`. 1071 #[allow(unused)] 1072 #[inline(always)] try_cast_into_no_leftover<U, R>( self, meta: Option<U::PointerMetadata>, ) -> Result<Ptr<'a, U, (I::Aliasing, Aligned, Initialized)>, CastError<Self, U>> where I::Aliasing: Reference, U: 'a + ?Sized + KnownLayout + Read<I::Aliasing, R>,1073 pub(crate) fn try_cast_into_no_leftover<U, R>( 1074 self, 1075 meta: Option<U::PointerMetadata>, 1076 ) -> Result<Ptr<'a, U, (I::Aliasing, Aligned, Initialized)>, CastError<Self, U>> 1077 where 1078 I::Aliasing: Reference, 1079 U: 'a + ?Sized + KnownLayout + Read<I::Aliasing, R>, 1080 { 1081 // TODO(#67): Remove this allow. See NonNulSlicelExt for more 1082 // details. 1083 #[allow(unstable_name_collisions)] 1084 match self.try_cast_into(CastType::Prefix, meta) { 1085 Ok((slf, remainder)) => { 1086 if remainder.len() == 0 { 1087 Ok(slf) 1088 } else { 1089 // Undo the cast so we can return the original bytes. 1090 let slf = slf.as_bytes(); 1091 // Restore the initial alignment invariant of `self`. 1092 // 1093 // SAFETY: The referent type of `slf` is now equal to 1094 // that of `self`, but the alignment invariants 1095 // nominally differ. Since `slf` and `self` refer to the 1096 // same memory and no actions have been taken that would 1097 // violate the original invariants on `self`, it is 1098 // sound to apply the alignment invariant of `self` onto 1099 // `slf`. 1100 let slf = unsafe { slf.assume_alignment::<I::Alignment>() }; 1101 let slf = slf.unify_invariants(); 1102 Err(CastError::Size(SizeError::<_, U>::new(slf))) 1103 } 1104 } 1105 Err(err) => Err(err), 1106 } 1107 } 1108 } 1109 1110 impl<'a, T, I> Ptr<'a, core::cell::UnsafeCell<T>, I> 1111 where 1112 T: 'a + ?Sized, 1113 I: Invariants<Aliasing = Exclusive>, 1114 { 1115 /// Converts this `Ptr` into a pointer to the underlying data. 1116 /// 1117 /// This call borrows the `UnsafeCell` mutably (at compile-time) which 1118 /// guarantees that we possess the only reference. 1119 /// 1120 /// This is like [`UnsafeCell::get_mut`], but for `Ptr`. 1121 /// 1122 /// [`UnsafeCell::get_mut`]: core::cell::UnsafeCell::get_mut 1123 #[must_use] 1124 #[inline(always)] get_mut(self) -> Ptr<'a, T, I>1125 pub fn get_mut(self) -> Ptr<'a, T, I> { 1126 // SAFETY: 1127 // - The closure uses an `as` cast, which preserves address 1128 // range and provenance. 1129 // - Aliasing is `Exclusive`, and so we are not required to promise 1130 // anything about the locations of `UnsafeCell`s. 1131 // - `UnsafeCell<T>` has the same bit validity as `T` [1], and so if 1132 // `self` has a particular validity invariant, then the same holds 1133 // of the returned `Ptr`. Technically the term "representation" 1134 // doesn't guarantee this, but the subsequent sentence in the 1135 // documentation makes it clear that this is the intention. 1136 // 1137 // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: 1138 // 1139 // `UnsafeCell<T>` has the same in-memory representation as its 1140 // inner type `T`. A consequence of this guarantee is that it is 1141 // possible to convert between `T` and `UnsafeCell<T>`. 1142 #[allow(clippy::as_conversions)] 1143 let ptr = unsafe { self.transmute_unchecked(|p| p as *mut T) }; 1144 1145 // SAFETY: `UnsafeCell<T>` has the same alignment as `T` [1], 1146 // and so if `self` is guaranteed to be aligned, then so is the 1147 // returned `Ptr`. 1148 // 1149 // [1] Per https://doc.rust-lang.org/1.81.0/core/cell/struct.UnsafeCell.html#memory-layout: 1150 // 1151 // `UnsafeCell<T>` has the same in-memory representation as 1152 // its inner type `T`. A consequence of this guarantee is that 1153 // it is possible to convert between `T` and `UnsafeCell<T>`. 1154 let ptr = unsafe { ptr.assume_alignment::<I::Alignment>() }; 1155 ptr.unify_invariants() 1156 } 1157 } 1158 } 1159 1160 /// Projections through the referent. 1161 mod _project { 1162 use super::*; 1163 1164 impl<'a, T, I> Ptr<'a, [T], I> 1165 where 1166 T: 'a, 1167 I: Invariants, 1168 { 1169 /// The number of slice elements in the object referenced by `self`. 1170 /// 1171 /// # Safety 1172 /// 1173 /// Unsafe code my rely on `len` satisfying the above contract. len(&self) -> usize1174 pub(crate) fn len(&self) -> usize { 1175 self.as_inner().len() 1176 } 1177 } 1178 1179 impl<'a, T, I> Ptr<'a, [T], I> 1180 where 1181 T: 'a, 1182 I: Invariants, 1183 I::Aliasing: Reference, 1184 { 1185 /// Iteratively projects the elements `Ptr<T>` from `Ptr<[T]>`. iter(&self) -> impl Iterator<Item = Ptr<'a, T, I>>1186 pub(crate) fn iter(&self) -> impl Iterator<Item = Ptr<'a, T, I>> { 1187 // SAFETY: 1188 // 0. `elem` conforms to the aliasing invariant of `I::Aliasing` 1189 // because projection does not impact the aliasing invariant. 1190 // 1. `elem`, conditionally, conforms to the validity invariant of 1191 // `I::Alignment`. If `elem` is projected from data well-aligned 1192 // for `[T]`, `elem` will be valid for `T`. 1193 // 2. `elem`, conditionally, conforms to the validity invariant of 1194 // `I::Validity`. If `elem` is projected from data valid for 1195 // `[T]`, `elem` will be valid for `T`. 1196 self.as_inner().iter().map(|elem| unsafe { Ptr::from_inner(elem) }) 1197 } 1198 } 1199 } 1200 1201 #[cfg(test)] 1202 mod tests { 1203 use core::mem::{self, MaybeUninit}; 1204 1205 use super::*; 1206 #[allow(unused)] // Needed on our MSRV, but considered unused on later toolchains. 1207 use crate::util::AsAddress; 1208 use crate::{pointer::BecauseImmutable, util::testutil::AU64, FromBytes, Immutable}; 1209 1210 mod test_ptr_try_cast_into_soundness { 1211 use super::*; 1212 1213 // This test is designed so that if `Ptr::try_cast_into_xxx` are 1214 // buggy, it will manifest as unsoundness that Miri can detect. 1215 1216 // - If `size_of::<T>() == 0`, `N == 4` 1217 // - Else, `N == 4 * size_of::<T>()` 1218 // 1219 // Each test will be run for each metadata in `metas`. test<T, I, const N: usize>(metas: I) where T: ?Sized + KnownLayout + Immutable + FromBytes, I: IntoIterator<Item = Option<T::PointerMetadata>> + Clone,1220 fn test<T, I, const N: usize>(metas: I) 1221 where 1222 T: ?Sized + KnownLayout + Immutable + FromBytes, 1223 I: IntoIterator<Item = Option<T::PointerMetadata>> + Clone, 1224 { 1225 let mut bytes = [MaybeUninit::<u8>::uninit(); N]; 1226 let initialized = [MaybeUninit::new(0u8); N]; 1227 for start in 0..=bytes.len() { 1228 for end in start..=bytes.len() { 1229 // Set all bytes to uninitialized other than those in 1230 // the range we're going to pass to `try_cast_from`. 1231 // This allows Miri to detect out-of-bounds reads 1232 // because they read uninitialized memory. Without this, 1233 // some out-of-bounds reads would still be in-bounds of 1234 // `bytes`, and so might spuriously be accepted. 1235 bytes = [MaybeUninit::<u8>::uninit(); N]; 1236 let bytes = &mut bytes[start..end]; 1237 // Initialize only the byte range we're going to pass to 1238 // `try_cast_from`. 1239 bytes.copy_from_slice(&initialized[start..end]); 1240 1241 let bytes = { 1242 let bytes: *const [MaybeUninit<u8>] = bytes; 1243 #[allow(clippy::as_conversions)] 1244 let bytes = bytes as *const [u8]; 1245 // SAFETY: We just initialized these bytes to valid 1246 // `u8`s. 1247 unsafe { &*bytes } 1248 }; 1249 1250 // SAFETY: The bytes in `slf` must be initialized. 1251 unsafe fn validate_and_get_len<T: ?Sized + KnownLayout + FromBytes>( 1252 slf: Ptr<'_, T, (Shared, Aligned, Initialized)>, 1253 ) -> usize { 1254 let t = slf.bikeshed_recall_valid().as_ref(); 1255 1256 let bytes = { 1257 let len = mem::size_of_val(t); 1258 let t: *const T = t; 1259 // SAFETY: 1260 // - We know `t`'s bytes are all initialized 1261 // because we just read it from `slf`, which 1262 // points to an initialized range of bytes. If 1263 // there's a bug and this doesn't hold, then 1264 // that's exactly what we're hoping Miri will 1265 // catch! 1266 // - Since `T: FromBytes`, `T` doesn't contain 1267 // any `UnsafeCell`s, so it's okay for `t: T` 1268 // and a `&[u8]` to the same memory to be 1269 // alive concurrently. 1270 unsafe { core::slice::from_raw_parts(t.cast::<u8>(), len) } 1271 }; 1272 1273 // This assertion ensures that `t`'s bytes are read 1274 // and compared to another value, which in turn 1275 // ensures that Miri gets a chance to notice if any 1276 // of `t`'s bytes are uninitialized, which they 1277 // shouldn't be (see the comment above). 1278 assert_eq!(bytes, vec![0u8; bytes.len()]); 1279 1280 mem::size_of_val(t) 1281 } 1282 1283 for meta in metas.clone().into_iter() { 1284 for cast_type in [CastType::Prefix, CastType::Suffix] { 1285 if let Ok((slf, remaining)) = Ptr::from_ref(bytes) 1286 .try_cast_into::<T, BecauseImmutable>(cast_type, meta) 1287 { 1288 // SAFETY: All bytes in `bytes` have been 1289 // initialized. 1290 let len = unsafe { validate_and_get_len(slf) }; 1291 assert_eq!(remaining.len(), bytes.len() - len); 1292 #[allow(unstable_name_collisions)] 1293 let bytes_addr = bytes.as_ptr().addr(); 1294 #[allow(unstable_name_collisions)] 1295 let remaining_addr = 1296 remaining.as_inner().as_non_null().as_ptr().addr(); 1297 match cast_type { 1298 CastType::Prefix => { 1299 assert_eq!(remaining_addr, bytes_addr + len) 1300 } 1301 CastType::Suffix => assert_eq!(remaining_addr, bytes_addr), 1302 } 1303 1304 if let Some(want) = meta { 1305 let got = KnownLayout::pointer_to_metadata( 1306 slf.as_inner().as_non_null().as_ptr(), 1307 ); 1308 assert_eq!(got, want); 1309 } 1310 } 1311 } 1312 1313 if let Ok(slf) = Ptr::from_ref(bytes) 1314 .try_cast_into_no_leftover::<T, BecauseImmutable>(meta) 1315 { 1316 // SAFETY: All bytes in `bytes` have been 1317 // initialized. 1318 let len = unsafe { validate_and_get_len(slf) }; 1319 assert_eq!(len, bytes.len()); 1320 1321 if let Some(want) = meta { 1322 let got = KnownLayout::pointer_to_metadata( 1323 slf.as_inner().as_non_null().as_ptr(), 1324 ); 1325 assert_eq!(got, want); 1326 } 1327 } 1328 } 1329 } 1330 } 1331 } 1332 1333 #[derive(FromBytes, KnownLayout, Immutable)] 1334 #[repr(C)] 1335 struct SliceDst<T> { 1336 a: u8, 1337 trailing: [T], 1338 } 1339 1340 // Each test case becomes its own `#[test]` function. We do this because 1341 // this test in particular takes far, far longer to execute under Miri 1342 // than all of our other tests combined. Previously, we had these 1343 // execute sequentially in a single test function. We run Miri tests in 1344 // parallel in CI, but this test being sequential meant that most of 1345 // that parallelism was wasted, as all other tests would finish in a 1346 // fraction of the total execution time, leaving this test to execute on 1347 // a single thread for the remainder of the test. By putting each test 1348 // case in its own function, we permit better use of available 1349 // parallelism. 1350 macro_rules! test { 1351 ($test_name:ident: $ty:ty) => { 1352 #[test] 1353 #[allow(non_snake_case)] 1354 fn $test_name() { 1355 const S: usize = core::mem::size_of::<$ty>(); 1356 const N: usize = if S == 0 { 4 } else { S * 4 }; 1357 test::<$ty, _, N>([None]); 1358 1359 // If `$ty` is a ZST, then we can't pass `None` as the 1360 // pointer metadata, or else computing the correct trailing 1361 // slice length will panic. 1362 if S == 0 { 1363 test::<[$ty], _, N>([Some(0), Some(1), Some(2), Some(3)]); 1364 test::<SliceDst<$ty>, _, N>([Some(0), Some(1), Some(2), Some(3)]); 1365 } else { 1366 test::<[$ty], _, N>([None, Some(0), Some(1), Some(2), Some(3)]); 1367 test::<SliceDst<$ty>, _, N>([None, Some(0), Some(1), Some(2), Some(3)]); 1368 } 1369 } 1370 }; 1371 ($ty:ident) => { 1372 test!($ty: $ty); 1373 }; 1374 ($($ty:ident),*) => { $(test!($ty);)* } 1375 } 1376 1377 test!(empty_tuple: ()); 1378 test!(u8, u16, u32, u64, u128, usize, AU64); 1379 test!(i8, i16, i32, i64, i128, isize); 1380 test!(f32, f64); 1381 } 1382 1383 #[test] test_try_cast_into_explicit_count()1384 fn test_try_cast_into_explicit_count() { 1385 macro_rules! test { 1386 ($ty:ty, $bytes:expr, $elems:expr, $expect:expr) => {{ 1387 let bytes = [0u8; $bytes]; 1388 let ptr = Ptr::from_ref(&bytes[..]); 1389 let res = 1390 ptr.try_cast_into::<$ty, BecauseImmutable>(CastType::Prefix, Some($elems)); 1391 if let Some(expect) = $expect { 1392 let (ptr, _) = res.unwrap(); 1393 assert_eq!( 1394 KnownLayout::pointer_to_metadata(ptr.as_inner().as_non_null().as_ptr()), 1395 expect 1396 ); 1397 } else { 1398 let _ = res.unwrap_err(); 1399 } 1400 }}; 1401 } 1402 1403 #[derive(KnownLayout, Immutable)] 1404 #[repr(C)] 1405 struct ZstDst { 1406 u: [u8; 8], 1407 slc: [()], 1408 } 1409 1410 test!(ZstDst, 8, 0, Some(0)); 1411 test!(ZstDst, 7, 0, None); 1412 1413 test!(ZstDst, 8, usize::MAX, Some(usize::MAX)); 1414 test!(ZstDst, 7, usize::MAX, None); 1415 1416 #[derive(KnownLayout, Immutable)] 1417 #[repr(C)] 1418 struct Dst { 1419 u: [u8; 8], 1420 slc: [u8], 1421 } 1422 1423 test!(Dst, 8, 0, Some(0)); 1424 test!(Dst, 7, 0, None); 1425 1426 test!(Dst, 9, 1, Some(1)); 1427 test!(Dst, 8, 1, None); 1428 1429 // If we didn't properly check for overflow, this would cause the 1430 // metadata to overflow to 0, and thus the cast would spuriously 1431 // succeed. 1432 test!(Dst, 8, usize::MAX - 8 + 1, None); 1433 } 1434 } 1435