xref: /linux/rust/zerocopy/src/util/mod.rs (revision c37398010a05055e78cf0c75defb90df06c4e999)
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