Skip to main content

zerocopy/util/
mod.rs

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