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 #[macro_use] 10 pub(crate) mod macros; 11 12 #[doc(hidden)] 13 pub mod macro_util; 14 15 use core::{ 16 marker::PhantomData, 17 mem::{self, ManuallyDrop}, 18 num::NonZeroUsize, 19 ptr::NonNull, 20 }; 21 22 use super::*; 23 use crate::pointer::{ 24 invariant::{Exclusive, Shared, Valid}, 25 SizeEq, TransmuteFromPtr, 26 }; 27 28 /// Like [`PhantomData`], but [`Send`] and [`Sync`] regardless of whether the 29 /// wrapped `T` is. 30 pub(crate) struct SendSyncPhantomData<T: ?Sized>(PhantomData<T>); 31 32 // SAFETY: `SendSyncPhantomData` does not enable any behavior which isn't sound 33 // to be called from multiple threads. 34 unsafe impl<T: ?Sized> Send for SendSyncPhantomData<T> {} 35 // SAFETY: `SendSyncPhantomData` does not enable any behavior which isn't sound 36 // to be called from multiple threads. 37 unsafe impl<T: ?Sized> Sync for SendSyncPhantomData<T> {} 38 39 impl<T: ?Sized> Default for SendSyncPhantomData<T> { 40 fn default() -> SendSyncPhantomData<T> { 41 SendSyncPhantomData(PhantomData) 42 } 43 } 44 45 impl<T: ?Sized> PartialEq for SendSyncPhantomData<T> { 46 fn eq(&self, _other: &Self) -> bool { 47 true 48 } 49 } 50 51 impl<T: ?Sized> Eq for SendSyncPhantomData<T> {} 52 53 impl<T: ?Sized> Clone for SendSyncPhantomData<T> { 54 fn clone(&self) -> Self { 55 SendSyncPhantomData(PhantomData) 56 } 57 } 58 59 #[cfg(miri)] 60 extern "Rust" { 61 /// Miri-provided intrinsic that marks the pointer `ptr` as aligned to 62 /// `align`. 63 /// 64 /// This intrinsic is used to inform Miri's symbolic alignment checker that 65 /// a pointer is aligned, even if Miri cannot statically deduce that fact. 66 /// This is often required when performing raw pointer arithmetic or casts 67 /// where the alignment is guaranteed by runtime checks or invariants that 68 /// Miri is not aware of. 69 pub(crate) fn miri_promise_symbolic_alignment(ptr: *const (), align: usize); 70 } 71 72 pub(crate) trait AsAddress { 73 fn addr(self) -> usize; 74 } 75 76 impl<T: ?Sized> AsAddress for &T { 77 #[inline(always)] 78 fn addr(self) -> usize { 79 let ptr: *const T = self; 80 AsAddress::addr(ptr) 81 } 82 } 83 84 impl<T: ?Sized> AsAddress for &mut T { 85 #[inline(always)] 86 fn addr(self) -> usize { 87 let ptr: *const T = self; 88 AsAddress::addr(ptr) 89 } 90 } 91 92 impl<T: ?Sized> AsAddress for NonNull<T> { 93 #[inline(always)] 94 fn addr(self) -> usize { 95 AsAddress::addr(self.as_ptr()) 96 } 97 } 98 99 impl<T: ?Sized> AsAddress for *const T { 100 #[inline(always)] 101 fn addr(self) -> usize { 102 // FIXME(#181), FIXME(https://github.com/rust-lang/rust/issues/95228): 103 // Use `.addr()` instead of `as usize` once it's stable, and get rid of 104 // this `allow`. Currently, `as usize` is the only way to accomplish 105 // this. 106 #[allow(clippy::as_conversions)] 107 #[cfg_attr( 108 __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS, 109 allow(lossy_provenance_casts) 110 )] 111 return self.cast::<()>() as usize; 112 } 113 } 114 115 impl<T: ?Sized> AsAddress for *mut T { 116 #[inline(always)] 117 fn addr(self) -> usize { 118 let ptr: *const T = self; 119 AsAddress::addr(ptr) 120 } 121 } 122 123 /// Validates that `t` is aligned to `align_of::<U>()`. 124 #[inline(always)] 125 pub(crate) fn validate_aligned_to<T: AsAddress, U>(t: T) -> Result<(), AlignmentError<(), U>> { 126 // `mem::align_of::<U>()` is guaranteed to return a non-zero value, which in 127 // turn guarantees that this mod operation will not panic. 128 #[allow(clippy::arithmetic_side_effects)] 129 let remainder = t.addr() % mem::align_of::<U>(); 130 if remainder == 0 { 131 Ok(()) 132 } else { 133 // SAFETY: We just confirmed that `t.addr() % align_of::<U>() != 0`. 134 // That's only possible if `align_of::<U>() > 1`. 135 Err(unsafe { AlignmentError::new_unchecked(()) }) 136 } 137 } 138 139 /// Returns the bytes needed to pad `len` to the next multiple of `align`. 140 /// 141 /// This function assumes that align is a power of two; there are no guarantees 142 /// on the answer it gives if this is not the case. 143 #[cfg_attr( 144 kani, 145 kani::requires(len <= DstLayout::MAX_SIZE), 146 kani::requires(align.is_power_of_two()), 147 kani::ensures(|&p| (len + p) % align.get() == 0), 148 // Ensures that we add the minimum required padding. 149 kani::ensures(|&p| p < align.get()), 150 )] 151 pub(crate) const fn padding_needed_for(len: usize, align: NonZeroUsize) -> usize { 152 #[cfg(kani)] 153 #[kani::proof_for_contract(padding_needed_for)] 154 fn proof() { 155 padding_needed_for(kani::any(), kani::any()); 156 } 157 158 // Abstractly, we want to compute: 159 // align - (len % align). 160 // Handling the case where len%align is 0. 161 // Because align is a power of two, len % align = len & (align-1). 162 // Guaranteed not to underflow as align is nonzero. 163 #[allow(clippy::arithmetic_side_effects)] 164 let mask = align.get() - 1; 165 166 // To efficiently subtract this value from align, we can use the bitwise 167 // complement. 168 // Note that ((!len) & (align-1)) gives us a number that with (len & 169 // (align-1)) sums to align-1. So subtracting 1 from x before taking the 170 // complement subtracts `len` from `align`. Some quick inspection of 171 // cases shows that this also handles the case where `len % align = 0` 172 // correctly too: len-1 % align then equals align-1, so the complement mod 173 // align will be 0, as desired. 174 // 175 // The following reasoning can be verified quickly by an SMT solver 176 // supporting the theory of bitvectors: 177 // ```smtlib 178 // ; Naive implementation of padding 179 // (define-fun padding1 ( 180 // (len (_ BitVec 32)) 181 // (align (_ BitVec 32))) (_ BitVec 32) 182 // (ite 183 // (= (_ bv0 32) (bvand len (bvsub align (_ bv1 32)))) 184 // (_ bv0 32) 185 // (bvsub align (bvand len (bvsub align (_ bv1 32)))))) 186 // 187 // ; The implementation below 188 // (define-fun padding2 ( 189 // (len (_ BitVec 32)) 190 // (align (_ BitVec 32))) (_ BitVec 32) 191 // (bvand (bvnot (bvsub len (_ bv1 32))) (bvsub align (_ bv1 32)))) 192 // 193 // (define-fun is-power-of-two ((x (_ BitVec 32))) Bool 194 // (= (_ bv0 32) (bvand x (bvsub x (_ bv1 32))))) 195 // 196 // (declare-const len (_ BitVec 32)) 197 // (declare-const align (_ BitVec 32)) 198 // ; Search for a case where align is a power of two and padding2 disagrees 199 // ; with padding1 200 // (assert (and (is-power-of-two align) 201 // (not (= (padding1 len align) (padding2 len align))))) 202 // (simplify (padding1 (_ bv300 32) (_ bv32 32))) ; 20 203 // (simplify (padding2 (_ bv300 32) (_ bv32 32))) ; 20 204 // (simplify (padding1 (_ bv322 32) (_ bv32 32))) ; 30 205 // (simplify (padding2 (_ bv322 32) (_ bv32 32))) ; 30 206 // (simplify (padding1 (_ bv8 32) (_ bv8 32))) ; 0 207 // (simplify (padding2 (_ bv8 32) (_ bv8 32))) ; 0 208 // (check-sat) ; unsat, also works for 64-bit bitvectors 209 // ``` 210 !(len.wrapping_sub(1)) & mask 211 } 212 213 /// Rounds `n` down to the largest value `m` such that `m <= n` and `m % align 214 /// == 0`. 215 /// 216 /// # Panics 217 /// 218 /// May panic if `align` is not a power of two. Even if it doesn't panic in this 219 /// case, it will produce nonsense results. 220 #[inline(always)] 221 #[cfg_attr( 222 kani, 223 kani::requires(align.is_power_of_two()), 224 kani::ensures(|&m| m <= n && m % align.get() == 0), 225 // Guarantees that `m` is the *largest* value such that `m % align == 0`. 226 kani::ensures(|&m| { 227 // If this `checked_add` fails, then the next multiple would wrap 228 // around, which trivially satisfies the "largest value" requirement. 229 m.checked_add(align.get()).map(|next_mul| next_mul > n).unwrap_or(true) 230 }) 231 )] 232 pub(crate) const fn round_down_to_next_multiple_of_alignment( 233 n: usize, 234 align: NonZeroUsize, 235 ) -> usize { 236 #[cfg(kani)] 237 #[kani::proof_for_contract(round_down_to_next_multiple_of_alignment)] 238 fn proof() { 239 round_down_to_next_multiple_of_alignment(kani::any(), kani::any()); 240 } 241 242 let align = align.get(); 243 #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))] 244 debug_assert!(align.is_power_of_two()); 245 246 // Subtraction can't underflow because `align.get() >= 1`. 247 #[allow(clippy::arithmetic_side_effects)] 248 let mask = !(align - 1); 249 n & mask 250 } 251 252 pub(crate) const fn max(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize { 253 if a.get() < b.get() { 254 b 255 } else { 256 a 257 } 258 } 259 260 pub(crate) const fn min(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize { 261 if a.get() > b.get() { 262 b 263 } else { 264 a 265 } 266 } 267 268 /// Copies `src` into the prefix of `dst`. 269 /// 270 /// # Safety 271 /// 272 /// The caller guarantees that `src.len() <= dst.len()`. 273 #[inline(always)] 274 pub(crate) unsafe fn copy_unchecked(src: &[u8], dst: &mut [u8]) { 275 debug_assert!(src.len() <= dst.len()); 276 // SAFETY: This invocation satisfies the safety contract of 277 // copy_nonoverlapping [1]: 278 // - `src.as_ptr()` is trivially valid for reads of `src.len()` bytes 279 // - `dst.as_ptr()` is valid for writes of `src.len()` bytes, because the 280 // caller has promised that `src.len() <= dst.len()` 281 // - `src` and `dst` are, trivially, properly aligned 282 // - the region of memory beginning at `src` with a size of `src.len()` 283 // bytes does not overlap with the region of memory beginning at `dst` 284 // with the same size, because `dst` is derived from an exclusive 285 // reference. 286 unsafe { 287 core::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len()); 288 }; 289 } 290 291 /// Unsafely transmutes the given `src` into a type `Dst`. 292 /// 293 /// # Safety 294 /// 295 /// The value `src` must be a valid instance of `Dst`. 296 #[inline(always)] 297 pub(crate) const unsafe fn transmute_unchecked<Src, Dst>(src: Src) -> Dst { 298 static_assert!(Src, Dst => core::mem::size_of::<Src>() == core::mem::size_of::<Dst>()); 299 300 #[repr(C)] 301 union Transmute<Src, Dst> { 302 src: ManuallyDrop<Src>, 303 dst: ManuallyDrop<Dst>, 304 } 305 306 // SAFETY: Since `Transmute<Src, Dst>` is `#[repr(C)]`, its `src` and `dst` 307 // fields both start at the same offset and the types of those fields are 308 // transparent wrappers around `Src` and `Dst` [1]. Consequently, 309 // initializing `Transmute` with with `src` and then reading out `dst` is 310 // equivalent to transmuting from `Src` to `Dst` [2]. Transmuting from `src` 311 // to `Dst` is valid because — by contract on the caller — `src` is a valid 312 // instance of `Dst`. 313 // 314 // [1] Per https://doc.rust-lang.org/1.82.0/std/mem/struct.ManuallyDrop.html: 315 // 316 // `ManuallyDrop<T>` is guaranteed to have the same layout and bit 317 // validity as `T`, and is subject to the same layout optimizations as 318 // `T`. 319 // 320 // [2] Per https://doc.rust-lang.org/1.82.0/reference/items/unions.html#reading-and-writing-union-fields: 321 // 322 // Effectively, writing to and then reading from a union with the C 323 // representation is analogous to a transmute from the type used for 324 // writing to the type used for reading. 325 unsafe { ManuallyDrop::into_inner(Transmute { src: ManuallyDrop::new(src) }.dst) } 326 } 327 328 /// # Safety 329 /// 330 /// `Src` must have a greater or equal alignment to `Dst`. 331 pub(crate) unsafe fn transmute_ref<Src, Dst, R>(src: &Src) -> &Dst 332 where 333 Src: ?Sized, 334 Dst: SizeEq<Src> 335 + TransmuteFromPtr<Src, Shared, Valid, Valid, <Dst as SizeEq<Src>>::CastFrom, R> 336 + ?Sized, 337 { 338 let dst = Ptr::from_ref(src).transmute(); 339 // SAFETY: The caller promises that `Src`'s alignment is at least as large 340 // as `Dst`'s alignment. 341 let dst = unsafe { dst.assume_alignment() }; 342 dst.as_ref() 343 } 344 345 /// # Safety 346 /// 347 /// `Src` must have a greater or equal alignment to `Dst`. 348 pub(crate) unsafe fn transmute_mut<Src, Dst, R>(src: &mut Src) -> &mut Dst 349 where 350 Src: ?Sized, 351 Dst: SizeEq<Src> 352 + TransmuteFromPtr<Src, Exclusive, Valid, Valid, <Dst as SizeEq<Src>>::CastFrom, R> 353 + ?Sized, 354 { 355 let dst = Ptr::from_mut(src).transmute(); 356 // SAFETY: The caller promises that `Src`'s alignment is at least as large 357 // as `Dst`'s alignment. 358 let dst = unsafe { dst.assume_alignment() }; 359 dst.as_mut() 360 } 361 362 /// Uses `allocate` to create a `Box<T>`. 363 /// 364 /// # Errors 365 /// 366 /// Returns an error on allocation failure. Allocation failure is guaranteed 367 /// never to cause a panic or an abort. 368 /// 369 /// # Safety 370 /// 371 /// `allocate` must be either `alloc::alloc::alloc` or 372 /// `alloc::alloc::alloc_zeroed`. The referent of the box returned by `new_box` 373 /// has the same bit-validity as the referent of the pointer returned by the 374 /// given `allocate` and sufficient size to store `T` with `meta`. 375 #[must_use = "has no side effects (other than allocation)"] 376 #[cfg(feature = "alloc")] 377 #[inline] 378 pub(crate) unsafe fn new_box<T>( 379 meta: T::PointerMetadata, 380 allocate: unsafe fn(core::alloc::Layout) -> *mut u8, 381 ) -> Result<alloc::boxed::Box<T>, AllocError> 382 where 383 T: ?Sized + crate::KnownLayout, 384 { 385 let align = T::LAYOUT.align.get(); 386 if !T::is_valid_metadata(meta) { 387 return Err(AllocError); 388 } 389 let size = match T::size_for_metadata(meta) { 390 Some(size) => size, 391 // Thanks to the `!T::is_valid_metadata(meta)` check 392 // above, this branch is unreachable. Fortunately, the 393 // optimizer recognizes this, so replacing this branch 394 // with `unreachable_unchecked` produces no codegen 395 // improvements. 396 None => return Err(AllocError), 397 }; 398 let ptr = if size != 0 { 399 // SAFETY: 400 // - `align` is derived from a `NonZeroUsize` and is thus non-zero. 401 // - `align` is a power of two because, by invariant on 402 // `KnownLayout::LAYOUT` `<T as KnownLayout>::LAYOUT` accurately 403 // reflects the layout of `T`. 404 // - `size`, by invariant on `size_for_metadata` is well-aligned for 405 // `align` and, by the check on `T::is_valid_metadata(meta)`, is less 406 // than `isize::MAX`. 407 let layout: Layout = unsafe { Layout::from_size_align_unchecked(size, align) }; 408 // SAFETY: By contract on the caller, `allocate` is either 409 // `alloc::alloc::alloc` or `alloc::alloc::alloc_zeroed`. The above 410 // check ensures their shared safety precondition: that the supplied 411 // layout is not zero-sized type [1]. 412 // 413 // [1] Per https://doc.rust-lang.org/1.81.0/std/alloc/trait.GlobalAlloc.html#tymethod.alloc: 414 // 415 // This function is unsafe because undefined behavior can result if 416 // the caller does not ensure that layout has non-zero size. 417 let ptr = unsafe { allocate(layout) }; 418 match NonNull::new(ptr) { 419 Some(ptr) => ptr, 420 None => return Err(AllocError), 421 } 422 } else { 423 // We use `transmute` instead of an `as` cast since Miri (with strict 424 // provenance enabled) notices and complains that an `as` cast creates a 425 // pointer with no provenance. Miri isn't smart enough to realize that 426 // we're only executing this branch when we're constructing a zero-sized 427 // `Box`, which doesn't require provenance. 428 // 429 // SAFETY: any initialized bit sequence is a bit-valid `*mut u8`. All 430 // bits of a `usize` are initialized. 431 // 432 // `#[allow(unknown_lints)]` is for `integer_to_ptr_transmutes` 433 #[allow(unknown_lints)] 434 #[allow(clippy::useless_transmute, integer_to_ptr_transmutes)] 435 let dangling = unsafe { mem::transmute::<usize, *mut u8>(align) }; 436 // SAFETY: `dangling` is constructed from `align`, which is derived from 437 // a `NonZeroUsize`, which is guaranteed to be non-zero. 438 // 439 // `Box<[T]>` does not allocate when `T` is zero-sized or when `len` is 440 // zero, but it does require a non-null dangling pointer for its 441 // allocation. 442 // 443 // FIXME(https://github.com/rust-lang/rust/issues/95228): Use 444 // `std::ptr::without_provenance` once it's stable. That may optimize 445 // better. As written, Rust may assume that this consumes "exposed" 446 // provenance, and thus Rust may have to assume that this may consume 447 // provenance from any pointer whose provenance has been exposed. 448 unsafe { NonNull::new_unchecked(dangling) } 449 }; 450 451 let ptr = T::raw_from_ptr_len(ptr, meta); 452 453 // FIXME(#429): Add a "SAFETY" comment and remove this `allow`. Make sure to 454 // include a justification that `ptr.as_ptr()` is validly-aligned in the ZST 455 // case (in which we manually construct a dangling pointer) and to justify 456 // why `Box` is safe to drop (it's because `allocate` uses the system 457 // allocator). 458 #[allow(clippy::undocumented_unsafe_blocks)] 459 Ok(unsafe { alloc::boxed::Box::from_raw(ptr.as_ptr()) }) 460 } 461 462 mod len_of { 463 use super::*; 464 465 /// A witness type for metadata of a valid instance of `&T`. 466 pub struct MetadataOf<T: ?Sized + KnownLayout> { 467 /// # Safety 468 /// 469 /// The size of an instance of `&T` with the given metadata is not 470 /// larger than `isize::MAX`. 471 meta: T::PointerMetadata, 472 _p: PhantomData<T>, 473 } 474 475 impl<T: ?Sized + KnownLayout> Copy for MetadataOf<T> {} 476 impl<T: ?Sized + KnownLayout> Clone for MetadataOf<T> { 477 #[inline] 478 fn clone(&self) -> Self { 479 *self 480 } 481 } 482 483 impl<T: ?Sized + KnownLayout> core::fmt::Debug for MetadataOf<T> 484 where 485 T::PointerMetadata: core::fmt::Debug, 486 { 487 #[inline] 488 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 489 f.debug_struct("MetadataOf").field("meta", &self.meta).finish() 490 } 491 } 492 493 impl<T: ?Sized> MetadataOf<T> 494 where 495 T: KnownLayout, 496 { 497 /// Returns `None` if `meta` is greater than `t`'s metadata. 498 #[inline(always)] 499 pub(crate) fn new_in_bounds(t: &T, meta: usize) -> Option<Self> 500 where 501 T: KnownLayout<PointerMetadata = usize>, 502 { 503 if meta <= Ptr::from_ref(t).len() { 504 // SAFETY: We have checked that `meta` is not greater than `t`'s 505 // metadata, which, by invariant on `&T`, addresses no more than 506 // `isize::MAX` bytes [1][2]. 507 // 508 // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety: 509 // 510 // For all types, `T: ?Sized`, and for all `t: &T` or `t: 511 // &mut T`, when such values cross an API boundary, the 512 // following invariants must generally be upheld: 513 // 514 // * `t` is non-null 515 // * `t` is aligned to `align_of_val(t)` 516 // * if `size_of_val(t) > 0`, then `t` is dereferenceable for 517 // `size_of_val(t)` many bytes 518 // 519 // If `t` points at address `a`, being "dereferenceable" for 520 // N bytes means that the memory range `[a, a + N)` is all 521 // contained within a single allocated object. 522 // 523 // [2] Per https://doc.rust-lang.org/1.85.0/std/ptr/index.html#allocated-object: 524 // 525 // For any allocated object with `base` address, `size`, and 526 // a set of `addresses`, the following are guaranteed: 527 // - For all addresses `a` in `addresses`, `a` is in the 528 // range `base .. (base + size)` (note that this requires 529 // `a < base + size`, not `a <= base + size`) 530 // - `base` is not equal to [`null()`] (i.e., the address 531 // with the numerical value 0) 532 // - `base + size <= usize::MAX` 533 // - `size <= isize::MAX` 534 Some(unsafe { Self::new_unchecked(meta) }) 535 } else { 536 None 537 } 538 } 539 540 /// # Safety 541 /// 542 /// The size of an instance of `&T` with the given metadata is not 543 /// larger than `isize::MAX`. 544 pub(crate) unsafe fn new_unchecked(meta: T::PointerMetadata) -> Self { 545 // SAFETY: The caller has promised that the size of an instance of 546 // `&T` with the given metadata is not larger than `isize::MAX`. 547 Self { meta, _p: PhantomData } 548 } 549 550 pub(crate) fn get(&self) -> T::PointerMetadata 551 where 552 T::PointerMetadata: Copy, 553 { 554 self.meta 555 } 556 557 #[inline] 558 pub(crate) fn padding_needed_for(&self) -> usize 559 where 560 T: KnownLayout<PointerMetadata = usize>, 561 { 562 let trailing_slice_layout = crate::trailing_slice_layout::<T>(); 563 564 // FIXME(#67): Remove this allow. See NumExt for more details. 565 #[allow( 566 unstable_name_collisions, 567 clippy::incompatible_msrv, 568 clippy::multiple_unsafe_ops_per_block 569 )] 570 // SAFETY: By invariant on `self`, a `&T` with metadata `self.meta` 571 // describes an object of size `<= isize::MAX`. This computes the 572 // size of such a `&T` without any trailing padding, and so neither 573 // the multiplication nor the addition will overflow. 574 let unpadded_size = unsafe { 575 let trailing_size = self.meta.unchecked_mul(trailing_slice_layout.elem_size); 576 trailing_size.unchecked_add(trailing_slice_layout.offset) 577 }; 578 579 util::padding_needed_for(unpadded_size, T::LAYOUT.align) 580 } 581 582 #[inline(always)] 583 pub(crate) fn validate_cast_and_convert_metadata( 584 addr: usize, 585 bytes_len: MetadataOf<[u8]>, 586 cast_type: CastType, 587 meta: Option<T::PointerMetadata>, 588 ) -> Result<(MetadataOf<T>, MetadataOf<[u8]>), MetadataCastError> { 589 let layout = match meta { 590 None => T::LAYOUT, 591 // This can return `Err(MetadataCastError::Size)` if the 592 // metadata describes an object which can't fit in an `isize`. 593 Some(meta) => { 594 if !T::is_valid_metadata(meta) { 595 return Err(MetadataCastError::Size); 596 } 597 let size = match T::size_for_metadata(meta) { 598 Some(size) => size, 599 // Thanks to the `!T::is_valid_metadata(meta)` check 600 // above, this branch is unreachable. Fortunately, the 601 // optimizer recognizes this, so replacing this branch 602 // with `unreachable_unchecked` produces no codegen 603 // improvements. 604 None => return Err(MetadataCastError::Size), 605 }; 606 DstLayout { 607 align: T::LAYOUT.align, 608 size_info: crate::SizeInfo::Sized { size }, 609 statically_shallow_unpadded: false, 610 } 611 } 612 }; 613 // Lemma 0: By contract on `validate_cast_and_convert_metadata`, if 614 // the result is `Ok(..)`, then a `&T` with `elems` trailing slice 615 // elements is no larger in size than `bytes_len.get()`. 616 let (elems, split_at) = 617 layout.validate_cast_and_convert_metadata(addr, bytes_len.get(), cast_type)?; 618 let elems = T::PointerMetadata::from_elem_count(elems); 619 620 // For a slice DST type, if `meta` is `Some(elems)`, then we 621 // synthesize `layout` to describe a sized type whose size is equal 622 // to the size of the instance that we are asked to cast. For sized 623 // types, `validate_cast_and_convert_metadata` returns `elems == 0`. 624 // Thus, in this case, we need to use the `elems` passed by the 625 // caller, not the one returned by 626 // `validate_cast_and_convert_metadata`. 627 // 628 // Lemma 1: A `&T` with `elems` trailing slice elements is no larger 629 // in size than `bytes_len.get()`. Proof: 630 // - If `meta` is `None`, then `elems` satisfies this condition by 631 // Lemma 0. 632 // - If `meta` is `Some(meta)`, then `layout` describes an object 633 // whose size is equal to the size of an `&T` with `meta` 634 // metadata. By Lemma 0, that size is not larger than 635 // `bytes_len.get()`. 636 // 637 // Lemma 2: A `&T` with `elems` trailing slice elements is no larger 638 // than `isize::MAX` bytes. Proof: By Lemma 1, a `&T` with metadata 639 // `elems` is not larger in size than `bytes_len.get()`. By 640 // invariant on `MetadataOf<[u8]>`, a `&[u8]` with metadata 641 // `bytes_len` is not larger than `isize::MAX`. Because 642 // `size_of::<u8>()` is `1`, a `&[u8]` with metadata `bytes_len` has 643 // size `bytes_len.get()` bytes. Therefore, a `&T` with metadata 644 // `elems` has size not larger than `isize::MAX`. 645 let elems = meta.unwrap_or(elems); 646 647 // SAFETY: See Lemma 2. 648 let elems = unsafe { MetadataOf::new_unchecked(elems) }; 649 650 // SAFETY: Let `size` be the size of a `&T` with metadata `elems`. 651 // By post-condition on `validate_cast_and_convert_metadata`, one of 652 // the following conditions holds: 653 // - `split_at == size`, in which case, by Lemma 2, `split_at <= 654 // isize::MAX`. Since `size_of::<u8>() == 1`, a `[u8]` with 655 // `split_at` elems has size not larger than `isize::MAX`. 656 // - `split_at == bytes_len - size`. Since `bytes_len: 657 // MetadataOf<u8>`, and since `size` is non-negative, `split_at` 658 // addresses no more bytes than `bytes_len` does. Since 659 // `bytes_len: MetadataOf<u8>`, `bytes_len` describes a `[u8]` 660 // which has no more than `isize::MAX` bytes, and thus so does 661 // `split_at`. 662 let split_at = unsafe { MetadataOf::<[u8]>::new_unchecked(split_at) }; 663 Ok((elems, split_at)) 664 } 665 } 666 } 667 668 pub use len_of::MetadataOf; 669 670 /// Since we support multiple versions of Rust, there are often features which 671 /// have been stabilized in the most recent stable release which do not yet 672 /// exist (stably) on our MSRV. This module provides polyfills for those 673 /// features so that we can write more "modern" code, and just remove the 674 /// polyfill once our MSRV supports the corresponding feature. Without this, 675 /// we'd have to write worse/more verbose code and leave FIXME comments 676 /// sprinkled throughout the codebase to update to the new pattern once it's 677 /// stabilized. 678 /// 679 /// Each trait is imported as `_` at the crate root; each polyfill should "just 680 /// work" at usage sites. 681 pub(crate) mod polyfills { 682 use core::ptr::{self, NonNull}; 683 684 // A polyfill for `NonNull::slice_from_raw_parts` that we can use before our 685 // MSRV is 1.70, when that function was stabilized. 686 // 687 // The `#[allow(unused)]` is necessary because, on sufficiently recent 688 // toolchain versions, `ptr.slice_from_raw_parts()` resolves to the inherent 689 // method rather than to this trait, and so this trait is considered unused. 690 // 691 // FIXME(#67): Once our MSRV is 1.70, remove this. 692 #[allow(unused)] 693 pub(crate) trait NonNullExt<T> { 694 fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]>; 695 } 696 697 impl<T> NonNullExt<T> for NonNull<T> { 698 // NOTE on coverage: this will never be tested in nightly since it's a 699 // polyfill for a feature which has been stabilized on our nightly 700 // toolchain. 701 #[cfg_attr( 702 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), 703 coverage(off) 704 )] 705 #[inline(always)] 706 fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]> { 707 let ptr = ptr::slice_from_raw_parts_mut(data.as_ptr(), len); 708 // SAFETY: `ptr` is converted from `data`, which is non-null. 709 unsafe { NonNull::new_unchecked(ptr) } 710 } 711 } 712 713 // A polyfill for `Self::unchecked_sub` that we can use until methods like 714 // `usize::unchecked_sub` is stabilized. 715 // 716 // The `#[allow(unused)]` is necessary because, on sufficiently recent 717 // toolchain versions, `ptr.slice_from_raw_parts()` resolves to the inherent 718 // method rather than to this trait, and so this trait is considered unused. 719 // 720 // FIXME(#67): Once our MSRV is high enough, remove this. 721 #[allow(unused)] 722 pub(crate) trait NumExt { 723 /// Add without checking for overflow. 724 /// 725 /// # Safety 726 /// 727 /// The caller promises that the addition will not overflow. 728 unsafe fn unchecked_add(self, rhs: Self) -> Self; 729 730 /// Subtract without checking for underflow. 731 /// 732 /// # Safety 733 /// 734 /// The caller promises that the subtraction will not underflow. 735 unsafe fn unchecked_sub(self, rhs: Self) -> Self; 736 737 /// Multiply without checking for overflow. 738 /// 739 /// # Safety 740 /// 741 /// The caller promises that the multiplication will not overflow. 742 unsafe fn unchecked_mul(self, rhs: Self) -> Self; 743 } 744 745 // NOTE on coverage: these will never be tested in nightly since they're 746 // polyfills for a feature which has been stabilized on our nightly 747 // toolchain. 748 impl NumExt for usize { 749 #[cfg_attr( 750 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), 751 coverage(off) 752 )] 753 #[inline(always)] 754 unsafe fn unchecked_add(self, rhs: usize) -> usize { 755 match self.checked_add(rhs) { 756 Some(x) => x, 757 None => { 758 // SAFETY: The caller promises that the addition will not 759 // underflow. 760 unsafe { core::hint::unreachable_unchecked() } 761 } 762 } 763 } 764 765 #[cfg_attr( 766 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), 767 coverage(off) 768 )] 769 #[inline(always)] 770 unsafe fn unchecked_sub(self, rhs: usize) -> usize { 771 match self.checked_sub(rhs) { 772 Some(x) => x, 773 None => { 774 // SAFETY: The caller promises that the subtraction will not 775 // underflow. 776 unsafe { core::hint::unreachable_unchecked() } 777 } 778 } 779 } 780 781 #[cfg_attr( 782 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), 783 coverage(off) 784 )] 785 #[inline(always)] 786 unsafe fn unchecked_mul(self, rhs: usize) -> usize { 787 match self.checked_mul(rhs) { 788 Some(x) => x, 789 None => { 790 // SAFETY: The caller promises that the multiplication will 791 // not overflow. 792 unsafe { core::hint::unreachable_unchecked() } 793 } 794 } 795 } 796 } 797 } 798 799 #[cfg(test)] 800 pub(crate) mod testutil { 801 use crate::*; 802 803 /// A `T` which is aligned to at least `align_of::<A>()`. 804 #[derive(Default)] 805 pub(crate) struct Align<T, A> { 806 pub(crate) t: T, 807 _a: [A; 0], 808 } 809 810 impl<T: Default, A> Align<T, A> { 811 pub(crate) fn set_default(&mut self) { 812 self.t = T::default(); 813 } 814 } 815 816 impl<T, A> Align<T, A> { 817 pub(crate) const fn new(t: T) -> Align<T, A> { 818 Align { t, _a: [] } 819 } 820 } 821 822 /// A `T` which is guaranteed not to satisfy `align_of::<A>()`. 823 /// 824 /// It must be the case that `align_of::<T>() < align_of::<A>()` in order 825 /// for this type to work properly. 826 #[repr(C)] 827 pub(crate) struct ForceUnalign<T: Unaligned, A> { 828 // The outer struct is aligned to `A`, and, thanks to `repr(C)`, `t` is 829 // placed at the minimum offset that guarantees its alignment. If 830 // `align_of::<T>() < align_of::<A>()`, then that offset will be 831 // guaranteed *not* to satisfy `align_of::<A>()`. 832 // 833 // Note that we need `T: Unaligned` in order to guarantee that there is 834 // no padding between `_u` and `t`. 835 _u: u8, 836 pub(crate) t: T, 837 _a: [A; 0], 838 } 839 840 impl<T: Unaligned, A> ForceUnalign<T, A> { 841 pub(crate) fn new(t: T) -> ForceUnalign<T, A> { 842 ForceUnalign { _u: 0, t, _a: [] } 843 } 844 } 845 // A `u64` with alignment 8. 846 // 847 // Though `u64` has alignment 8 on some platforms, it's not guaranteed. By 848 // contrast, `AU64` is guaranteed to have alignment 8 on all platforms. 849 #[derive( 850 KnownLayout, 851 Immutable, 852 FromBytes, 853 IntoBytes, 854 Eq, 855 PartialEq, 856 Ord, 857 PartialOrd, 858 Default, 859 Debug, 860 Copy, 861 Clone, 862 )] 863 #[repr(C, align(8))] 864 pub(crate) struct AU64(pub(crate) u64); 865 866 impl AU64 { 867 // Converts this `AU64` to bytes using this platform's endianness. 868 pub(crate) fn to_bytes(self) -> [u8; 8] { 869 crate::transmute!(self) 870 } 871 } 872 873 impl Display for AU64 { 874 #[cfg_attr( 875 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS), 876 coverage(off) 877 )] 878 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 879 Display::fmt(&self.0, f) 880 } 881 } 882 } 883 884 #[cfg(test)] 885 mod tests { 886 use super::*; 887 888 #[test] 889 fn test_round_down_to_next_multiple_of_alignment() { 890 fn alt_impl(n: usize, align: NonZeroUsize) -> usize { 891 let mul = n / align.get(); 892 mul * align.get() 893 } 894 895 for align in [1, 2, 4, 8, 16] { 896 for n in 0..256 { 897 let align = NonZeroUsize::new(align).unwrap(); 898 let want = alt_impl(n, align); 899 let got = round_down_to_next_multiple_of_alignment(n, align); 900 assert_eq!(got, want, "round_down_to_next_multiple_of_alignment({}, {})", n, align); 901 } 902 } 903 } 904 905 #[rustversion::since(1.57.0)] 906 #[test] 907 #[should_panic] 908 fn test_round_down_to_next_multiple_of_alignment_zerocopy_panic_in_const_and_vec_try_reserve() { 909 round_down_to_next_multiple_of_alignment(0, NonZeroUsize::new(3).unwrap()); 910 } 911 #[test] 912 fn test_send_sync_phantom_data() { 913 let x = SendSyncPhantomData::<u8>::default(); 914 let y = x.clone(); 915 assert!(x == y); 916 assert!(x == SendSyncPhantomData::<u8>::default()); 917 } 918 919 #[test] 920 #[allow(clippy::as_conversions)] 921 fn test_as_address() { 922 let x = 0u8; 923 let r = &x; 924 let mut x_mut = 0u8; 925 let rm = &mut x_mut; 926 let p = r as *const u8; 927 let pm = rm as *mut u8; 928 let nn = NonNull::new(p as *mut u8).unwrap(); 929 930 assert_eq!(AsAddress::addr(r), p as usize); 931 assert_eq!(AsAddress::addr(rm), pm as usize); 932 assert_eq!(AsAddress::addr(p), p as usize); 933 assert_eq!(AsAddress::addr(pm), pm as usize); 934 assert_eq!(AsAddress::addr(nn), p as usize); 935 } 936 } 937