zerocopy/util/mod.rs
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]
10pub(crate) mod macros;
11
12#[doc(hidden)]
13pub mod macro_util;
14
15use core::{
16 marker::PhantomData,
17 mem::{self, ManuallyDrop},
18 num::NonZeroUsize,
19 ptr::NonNull,
20};
21
22use super::*;
23use 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.
30pub(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.
34unsafe 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.
37unsafe impl<T: ?Sized> Sync for SendSyncPhantomData<T> {}
38
39impl<T: ?Sized> Default for SendSyncPhantomData<T> {
40 fn default() -> SendSyncPhantomData<T> {
41 SendSyncPhantomData(PhantomData)
42 }
43}
44
45impl<T: ?Sized> PartialEq for SendSyncPhantomData<T> {
46 fn eq(&self, _other: &Self) -> bool {
47 true
48 }
49}
50
51impl<T: ?Sized> Eq for SendSyncPhantomData<T> {}
52
53impl<T: ?Sized> Clone for SendSyncPhantomData<T> {
54 fn clone(&self) -> Self {
55 SendSyncPhantomData(PhantomData)
56 }
57}
58
59#[cfg(miri)]
60extern "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
72pub(crate) trait AsAddress {
73 fn addr(self) -> usize;
74}
75
76impl<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
84impl<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
92impl<T: ?Sized> AsAddress for NonNull<T> {
93 #[inline(always)]
94 fn addr(self) -> usize {
95 AsAddress::addr(self.as_ptr())
96 }
97}
98
99impl<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
115impl<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)]
125pub(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)]
151pub(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)]
232pub(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
252pub(crate) const fn max(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize {
253 if a.get() < b.get() {
254 b
255 } else {
256 a
257 }
258}
259
260pub(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)]
274pub(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)]
297pub(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`.
331pub(crate) unsafe fn transmute_ref<Src, Dst, R>(src: &Src) -> &Dst
332where
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`.
348pub(crate) unsafe fn transmute_mut<Src, Dst, R>(src: &mut Src) -> &mut Dst
349where
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]
378pub(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>
382where
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
462mod 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
668pub 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.
681pub(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)]
800pub(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)]
885mod 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}