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