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