Coverage Report

Created: 2026-03-07 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerocopy-0.8.40/src/util/mod.rs
Line
Count
Source
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
0
    fn default() -> SendSyncPhantomData<T> {
41
0
        SendSyncPhantomData(PhantomData)
42
0
    }
43
}
44
45
impl<T: ?Sized> PartialEq for SendSyncPhantomData<T> {
46
0
    fn eq(&self, _other: &Self) -> bool {
47
0
        true
48
0
    }
49
}
50
51
impl<T: ?Sized> Eq for SendSyncPhantomData<T> {}
52
53
impl<T: ?Sized> Clone for SendSyncPhantomData<T> {
54
0
    fn clone(&self) -> Self {
55
0
        SendSyncPhantomData(PhantomData)
56
0
    }
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
0
    fn addr(self) -> usize {
79
0
        let ptr: *const T = self;
80
0
        AsAddress::addr(ptr)
81
0
    }
82
}
83
84
impl<T: ?Sized> AsAddress for &mut T {
85
    #[inline(always)]
86
0
    fn addr(self) -> usize {
87
0
        let ptr: *const T = self;
88
0
        AsAddress::addr(ptr)
89
0
    }
90
}
91
92
impl<T: ?Sized> AsAddress for NonNull<T> {
93
    #[inline(always)]
94
0
    fn addr(self) -> usize {
95
0
        AsAddress::addr(self.as_ptr())
96
0
    }
97
}
98
99
impl<T: ?Sized> AsAddress for *const T {
100
    #[inline(always)]
101
0
    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
0
        return self.cast::<()>() as usize;
112
0
    }
113
}
114
115
impl<T: ?Sized> AsAddress for *mut T {
116
    #[inline(always)]
117
0
    fn addr(self) -> usize {
118
0
        let ptr: *const T = self;
119
0
        AsAddress::addr(ptr)
120
0
    }
121
}
122
123
/// Validates that `t` is aligned to `align_of::<U>()`.
124
#[inline(always)]
125
0
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
0
    let remainder = t.addr() % mem::align_of::<U>();
130
0
    if remainder == 0 {
131
0
        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
0
        Err(unsafe { AlignmentError::new_unchecked(()) })
136
    }
137
0
}
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 <= isize::MAX as usize),
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
0
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
0
    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
0
    !(len.wrapping_sub(1)) & mask
211
0
}
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
0
pub(crate) const fn round_down_to_next_multiple_of_alignment(
233
0
    n: usize,
234
0
    align: NonZeroUsize,
235
0
) -> 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
0
    let align = align.get();
243
    #[cfg(not(no_zerocopy_panic_in_const_and_vec_try_reserve_1_57_0))]
244
0
    debug_assert!(align.is_power_of_two());
245
246
    // Subtraction can't underflow because `align.get() >= 1`.
247
    #[allow(clippy::arithmetic_side_effects)]
248
0
    let mask = !(align - 1);
249
0
    n & mask
250
0
}
251
252
0
pub(crate) const fn max(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize {
253
0
    if a.get() < b.get() {
254
0
        b
255
    } else {
256
0
        a
257
    }
258
0
}
259
260
0
pub(crate) const fn min(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize {
261
0
    if a.get() > b.get() {
262
0
        b
263
    } else {
264
0
        a
265
    }
266
0
}
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
0
pub(crate) unsafe fn copy_unchecked(src: &[u8], dst: &mut [u8]) {
275
0
    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
0
    unsafe {
287
0
        core::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
288
0
    };
289
0
}
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
0
pub(crate) const unsafe fn transmute_unchecked<Src, Dst>(src: Src) -> Dst {
298
0
    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
0
    unsafe { ManuallyDrop::into_inner(Transmute { src: ManuallyDrop::new(src) }.dst) }
326
0
}
327
328
/// # Safety
329
///
330
/// `Src` must have a greater or equal alignment to `Dst`.
331
0
pub(crate) unsafe fn transmute_ref<Src, Dst, R>(src: &Src) -> &Dst
332
0
where
333
0
    Src: ?Sized,
334
0
    Dst: SizeEq<Src>
335
0
        + TransmuteFromPtr<Src, Shared, Valid, Valid, <Dst as SizeEq<Src>>::CastFrom, R>
336
0
        + ?Sized,
337
{
338
0
    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
0
    let dst = unsafe { dst.assume_alignment() };
342
0
    dst.as_ref()
343
0
}
344
345
/// # Safety
346
///
347
/// `Src` must have a greater or equal alignment to `Dst`.
348
0
pub(crate) unsafe fn transmute_mut<Src, Dst, R>(src: &mut Src) -> &mut Dst
349
0
where
350
0
    Src: ?Sized,
351
0
    Dst: SizeEq<Src>
352
0
        + TransmuteFromPtr<Src, Exclusive, Valid, Valid, <Dst as SizeEq<Src>>::CastFrom, R>
353
0
        + ?Sized,
354
{
355
0
    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
0
    let dst = unsafe { dst.assume_alignment() };
359
0
    dst.as_mut()
360
0
}
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 size = match T::size_for_metadata(meta) {
386
        Some(size) => size,
387
        None => return Err(AllocError),
388
    };
389
390
    let align = T::LAYOUT.align.get();
391
    // On stable Rust versions <= 1.64.0, `Layout::from_size_align` has a bug in
392
    // which sufficiently-large allocations (those which, when rounded up to the
393
    // alignment, overflow `isize`) are not rejected, which can cause undefined
394
    // behavior. See #64 for details.
395
    //
396
    // FIXME(#67): Once our MSRV is > 1.64.0, remove this assertion.
397
    #[allow(clippy::as_conversions)]
398
    let max_alloc = (isize::MAX as usize).saturating_sub(align);
399
    if size > max_alloc {
400
        return Err(AllocError);
401
    }
402
403
    // FIXME(https://github.com/rust-lang/rust/issues/55724): Use
404
    // `Layout::repeat` once it's stabilized.
405
    let layout = Layout::from_size_align(size, align).or(Err(AllocError))?;
406
407
    let ptr = if layout.size() != 0 {
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
        let align = T::LAYOUT.align.get();
424
425
        // We use `transmute` instead of an `as` cast since Miri (with strict
426
        // provenance enabled) notices and complains that an `as` cast creates a
427
        // pointer with no provenance. Miri isn't smart enough to realize that
428
        // we're only executing this branch when we're constructing a zero-sized
429
        // `Box`, which doesn't require provenance.
430
        //
431
        // SAFETY: any initialized bit sequence is a bit-valid `*mut u8`. All
432
        // bits of a `usize` are initialized.
433
        //
434
        // `#[allow(unknown_lints)]` is for `integer_to_ptr_transmutes`
435
        #[allow(unknown_lints)]
436
        #[allow(clippy::useless_transmute, integer_to_ptr_transmutes)]
437
        let dangling = unsafe { mem::transmute::<usize, *mut u8>(align) };
438
        // SAFETY: `dangling` is constructed from `T::LAYOUT.align`, which is a
439
        // `NonZeroUsize`, which is guaranteed to be non-zero.
440
        //
441
        // `Box<[T]>` does not allocate when `T` is zero-sized or when `len` is
442
        // zero, but it does require a non-null dangling pointer for its
443
        // allocation.
444
        //
445
        // FIXME(https://github.com/rust-lang/rust/issues/95228): Use
446
        // `std::ptr::without_provenance` once it's stable. That may optimize
447
        // better. As written, Rust may assume that this consumes "exposed"
448
        // provenance, and thus Rust may have to assume that this may consume
449
        // provenance from any pointer whose provenance has been exposed.
450
        unsafe { NonNull::new_unchecked(dangling) }
451
    };
452
453
    let ptr = T::raw_from_ptr_len(ptr, meta);
454
455
    // FIXME(#429): Add a "SAFETY" comment and remove this `allow`. Make sure to
456
    // include a justification that `ptr.as_ptr()` is validly-aligned in the ZST
457
    // case (in which we manually construct a dangling pointer) and to justify
458
    // why `Box` is safe to drop (it's because `allocate` uses the system
459
    // allocator).
460
    #[allow(clippy::undocumented_unsafe_blocks)]
461
    Ok(unsafe { alloc::boxed::Box::from_raw(ptr.as_ptr()) })
462
}
463
464
mod len_of {
465
    use super::*;
466
467
    /// A witness type for metadata of a valid instance of `&T`.
468
    pub(crate) struct MetadataOf<T: ?Sized + KnownLayout> {
469
        /// # Safety
470
        ///
471
        /// The size of an instance of `&T` with the given metadata is not
472
        /// larger than `isize::MAX`.
473
        meta: T::PointerMetadata,
474
        _p: PhantomData<T>,
475
    }
476
477
    impl<T: ?Sized + KnownLayout> Copy for MetadataOf<T> {}
478
    impl<T: ?Sized + KnownLayout> Clone for MetadataOf<T> {
479
0
        fn clone(&self) -> Self {
480
0
            *self
481
0
        }
482
    }
483
484
    impl<T: ?Sized> MetadataOf<T>
485
    where
486
        T: KnownLayout,
487
    {
488
        /// Returns `None` if `meta` is greater than `t`'s metadata.
489
        #[inline(always)]
490
0
        pub(crate) fn new_in_bounds(t: &T, meta: usize) -> Option<Self>
491
0
        where
492
0
            T: KnownLayout<PointerMetadata = usize>,
493
        {
494
0
            if meta <= Ptr::from_ref(t).len() {
495
                // SAFETY: We have checked that `meta` is not greater than `t`'s
496
                // metadata, which, by invariant on `&T`, addresses no more than
497
                // `isize::MAX` bytes [1][2].
498
                //
499
                // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety:
500
                //
501
                //    For all types, `T: ?Sized`, and for all `t: &T` or `t:
502
                //    &mut T`, when such values cross an API boundary, the
503
                //    following invariants must generally be upheld:
504
                //
505
                //    * `t` is non-null
506
                //    * `t` is aligned to `align_of_val(t)`
507
                //    * if `size_of_val(t) > 0`, then `t` is dereferenceable for
508
                //      `size_of_val(t)` many bytes
509
                //
510
                //    If `t` points at address `a`, being "dereferenceable" for
511
                //    N bytes means that the memory range `[a, a + N)` is all
512
                //    contained within a single allocated object.
513
                //
514
                // [2] Per https://doc.rust-lang.org/1.85.0/std/ptr/index.html#allocated-object:
515
                //
516
                //    For any allocated object with `base` address, `size`, and
517
                //    a set of `addresses`, the following are guaranteed:
518
                //    - For all addresses `a` in `addresses`, `a` is in the
519
                //      range `base .. (base + size)` (note that this requires
520
                //      `a < base + size`, not `a <= base + size`)
521
                //    - `base` is not equal to [`null()`] (i.e., the address
522
                //      with the numerical value 0)
523
                //    - `base + size <= usize::MAX`
524
                //    - `size <= isize::MAX`
525
0
                Some(unsafe { Self::new_unchecked(meta) })
526
            } else {
527
0
                None
528
            }
529
0
        }
530
531
        /// # Safety
532
        ///
533
        /// The size of an instance of `&T` with the given metadata is not
534
        /// larger than `isize::MAX`.
535
0
        pub(crate) unsafe fn new_unchecked(meta: T::PointerMetadata) -> Self {
536
            // SAFETY: The caller has promised that the size of an instance of
537
            // `&T` with the given metadata is not larger than `isize::MAX`.
538
0
            Self { meta, _p: PhantomData }
539
0
        }
540
541
0
        pub(crate) fn get(&self) -> T::PointerMetadata
542
0
        where
543
0
            T::PointerMetadata: Copy,
544
        {
545
0
            self.meta
546
0
        }
547
548
        #[inline]
549
0
        pub(crate) fn padding_needed_for(&self) -> usize
550
0
        where
551
0
            T: KnownLayout<PointerMetadata = usize>,
552
        {
553
0
            let trailing_slice_layout = crate::trailing_slice_layout::<T>();
554
555
            // FIXME(#67): Remove this allow. See NumExt for more details.
556
            #[allow(
557
                unstable_name_collisions,
558
                clippy::incompatible_msrv,
559
                clippy::multiple_unsafe_ops_per_block
560
            )]
561
            // SAFETY: By invariant on `self`, a `&T` with metadata `self.meta`
562
            // describes an object of size `<= isize::MAX`. This computes the
563
            // size of such a `&T` without any trailing padding, and so neither
564
            // the multiplication nor the addition will overflow.
565
0
            let unpadded_size = unsafe {
566
0
                let trailing_size = self.meta.unchecked_mul(trailing_slice_layout.elem_size);
567
0
                trailing_size.unchecked_add(trailing_slice_layout.offset)
568
            };
569
570
0
            util::padding_needed_for(unpadded_size, T::LAYOUT.align)
571
0
        }
572
573
        #[inline(always)]
574
0
        pub(crate) fn validate_cast_and_convert_metadata(
575
0
            addr: usize,
576
0
            bytes_len: MetadataOf<[u8]>,
577
0
            cast_type: CastType,
578
0
            meta: Option<T::PointerMetadata>,
579
0
        ) -> Result<(MetadataOf<T>, MetadataOf<[u8]>), MetadataCastError> {
580
0
            let layout = match meta {
581
0
                None => T::LAYOUT,
582
                // This can return `None` if the metadata describes an object
583
                // which can't fit in an `isize`.
584
0
                Some(meta) => {
585
0
                    let size = match T::size_for_metadata(meta) {
586
0
                        Some(size) => size,
587
0
                        None => return Err(MetadataCastError::Size),
588
                    };
589
0
                    DstLayout {
590
0
                        align: T::LAYOUT.align,
591
0
                        size_info: crate::SizeInfo::Sized { size },
592
0
                        statically_shallow_unpadded: false,
593
0
                    }
594
                }
595
            };
596
            // Lemma 0: By contract on `validate_cast_and_convert_metadata`, if
597
            // the result is `Ok(..)`, then a `&T` with `elems` trailing slice
598
            // elements is no larger in size than `bytes_len.get()`.
599
0
            let (elems, split_at) =
600
0
                layout.validate_cast_and_convert_metadata(addr, bytes_len.get(), cast_type)?;
601
0
            let elems = T::PointerMetadata::from_elem_count(elems);
602
603
            // For a slice DST type, if `meta` is `Some(elems)`, then we
604
            // synthesize `layout` to describe a sized type whose size is equal
605
            // to the size of the instance that we are asked to cast. For sized
606
            // types, `validate_cast_and_convert_metadata` returns `elems == 0`.
607
            // Thus, in this case, we need to use the `elems` passed by the
608
            // caller, not the one returned by
609
            // `validate_cast_and_convert_metadata`.
610
            //
611
            // Lemma 1: A `&T` with `elems` trailing slice elements is no larger
612
            // in size than `bytes_len.get()`. Proof:
613
            // - If `meta` is `None`, then `elems` satisfies this condition by
614
            //   Lemma 0.
615
            // - If `meta` is `Some(meta)`, then `layout` describes an object
616
            //   whose size is equal to the size of an `&T` with `meta`
617
            //   metadata. By Lemma 0, that size is not larger than
618
            //   `bytes_len.get()`.
619
            //
620
            // Lemma 2: A `&T` with `elems` trailing slice elements is no larger
621
            // than `isize::MAX` bytes. Proof: By Lemma 1, a `&T` with metadata
622
            // `elems` is not larger in size than `bytes_len.get()`. By
623
            // invariant on `MetadataOf<[u8]>`, a `&[u8]` with metadata
624
            // `bytes_len` is not larger than `isize::MAX`. Because
625
            // `size_of::<u8>()` is `1`, a `&[u8]` with metadata `bytes_len` has
626
            // size `bytes_len.get()` bytes. Therefore, a `&T` with metadata
627
            // `elems` has size not larger than `isize::MAX`.
628
0
            let elems = meta.unwrap_or(elems);
629
630
            // SAFETY: See Lemma 2.
631
0
            let elems = unsafe { MetadataOf::new_unchecked(elems) };
632
633
            // SAFETY: Let `size` be the size of a `&T` with metadata `elems`.
634
            // By post-condition on `validate_cast_and_convert_metadata`, one of
635
            // the following conditions holds:
636
            // - `split_at == size`, in which case, by Lemma 2, `split_at <=
637
            //   isize::MAX`. Since `size_of::<u8>() == 1`, a `[u8]` with
638
            //   `split_at` elems has size not larger than `isize::MAX`.
639
            // - `split_at == bytes_len - size`. Since `bytes_len:
640
            //   MetadataOf<u8>`, and since `size` is non-negative, `split_at`
641
            //   addresses no more bytes than `bytes_len` does. Since
642
            //   `bytes_len: MetadataOf<u8>`, `bytes_len` describes a `[u8]`
643
            //   which has no more than `isize::MAX` bytes, and thus so does
644
            //   `split_at`.
645
0
            let split_at = unsafe { MetadataOf::<[u8]>::new_unchecked(split_at) };
646
0
            Ok((elems, split_at))
647
0
        }
648
    }
649
}
650
651
pub(crate) use len_of::MetadataOf;
652
653
/// Since we support multiple versions of Rust, there are often features which
654
/// have been stabilized in the most recent stable release which do not yet
655
/// exist (stably) on our MSRV. This module provides polyfills for those
656
/// features so that we can write more "modern" code, and just remove the
657
/// polyfill once our MSRV supports the corresponding feature. Without this,
658
/// we'd have to write worse/more verbose code and leave FIXME comments
659
/// sprinkled throughout the codebase to update to the new pattern once it's
660
/// stabilized.
661
///
662
/// Each trait is imported as `_` at the crate root; each polyfill should "just
663
/// work" at usage sites.
664
pub(crate) mod polyfills {
665
    use core::ptr::{self, NonNull};
666
667
    // A polyfill for `NonNull::slice_from_raw_parts` that we can use before our
668
    // MSRV is 1.70, when that function was stabilized.
669
    //
670
    // The `#[allow(unused)]` is necessary because, on sufficiently recent
671
    // toolchain versions, `ptr.slice_from_raw_parts()` resolves to the inherent
672
    // method rather than to this trait, and so this trait is considered unused.
673
    //
674
    // FIXME(#67): Once our MSRV is 1.70, remove this.
675
    #[allow(unused)]
676
    pub(crate) trait NonNullExt<T> {
677
        fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]>;
678
    }
679
680
    impl<T> NonNullExt<T> for NonNull<T> {
681
        // NOTE on coverage: this will never be tested in nightly since it's a
682
        // polyfill for a feature which has been stabilized on our nightly
683
        // toolchain.
684
        #[cfg_attr(
685
            all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
686
            coverage(off)
687
        )]
688
        #[inline(always)]
689
0
        fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]> {
690
0
            let ptr = ptr::slice_from_raw_parts_mut(data.as_ptr(), len);
691
            // SAFETY: `ptr` is converted from `data`, which is non-null.
692
0
            unsafe { NonNull::new_unchecked(ptr) }
693
0
        }
694
    }
695
696
    // A polyfill for `Self::unchecked_sub` that we can use until methods like
697
    // `usize::unchecked_sub` is stabilized.
698
    //
699
    // The `#[allow(unused)]` is necessary because, on sufficiently recent
700
    // toolchain versions, `ptr.slice_from_raw_parts()` resolves to the inherent
701
    // method rather than to this trait, and so this trait is considered unused.
702
    //
703
    // FIXME(#67): Once our MSRV is high enough, remove this.
704
    #[allow(unused)]
705
    pub(crate) trait NumExt {
706
        /// Add without checking for overflow.
707
        ///
708
        /// # Safety
709
        ///
710
        /// The caller promises that the addition will not overflow.
711
        unsafe fn unchecked_add(self, rhs: Self) -> Self;
712
713
        /// Subtract without checking for underflow.
714
        ///
715
        /// # Safety
716
        ///
717
        /// The caller promises that the subtraction will not underflow.
718
        unsafe fn unchecked_sub(self, rhs: Self) -> Self;
719
720
        /// Multiply without checking for overflow.
721
        ///
722
        /// # Safety
723
        ///
724
        /// The caller promises that the multiplication will not overflow.
725
        unsafe fn unchecked_mul(self, rhs: Self) -> Self;
726
    }
727
728
    // NOTE on coverage: these will never be tested in nightly since they're
729
    // polyfills for a feature which has been stabilized on our nightly
730
    // toolchain.
731
    impl NumExt for usize {
732
        #[cfg_attr(
733
            all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
734
            coverage(off)
735
        )]
736
        #[inline(always)]
737
0
        unsafe fn unchecked_add(self, rhs: usize) -> usize {
738
0
            match self.checked_add(rhs) {
739
0
                Some(x) => x,
740
                None => {
741
                    // SAFETY: The caller promises that the addition will not
742
                    // underflow.
743
0
                    unsafe { core::hint::unreachable_unchecked() }
744
                }
745
            }
746
0
        }
747
748
        #[cfg_attr(
749
            all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
750
            coverage(off)
751
        )]
752
        #[inline(always)]
753
0
        unsafe fn unchecked_sub(self, rhs: usize) -> usize {
754
0
            match self.checked_sub(rhs) {
755
0
                Some(x) => x,
756
                None => {
757
                    // SAFETY: The caller promises that the subtraction will not
758
                    // underflow.
759
0
                    unsafe { core::hint::unreachable_unchecked() }
760
                }
761
            }
762
0
        }
763
764
        #[cfg_attr(
765
            all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
766
            coverage(off)
767
        )]
768
        #[inline(always)]
769
0
        unsafe fn unchecked_mul(self, rhs: usize) -> usize {
770
0
            match self.checked_mul(rhs) {
771
0
                Some(x) => x,
772
                None => {
773
                    // SAFETY: The caller promises that the multiplication will
774
                    // not overflow.
775
0
                    unsafe { core::hint::unreachable_unchecked() }
776
                }
777
            }
778
0
        }
779
    }
780
}
781
782
#[cfg(test)]
783
pub(crate) mod testutil {
784
    use crate::*;
785
786
    /// A `T` which is aligned to at least `align_of::<A>()`.
787
    #[derive(Default)]
788
    pub(crate) struct Align<T, A> {
789
        pub(crate) t: T,
790
        _a: [A; 0],
791
    }
792
793
    impl<T: Default, A> Align<T, A> {
794
        pub(crate) fn set_default(&mut self) {
795
            self.t = T::default();
796
        }
797
    }
798
799
    impl<T, A> Align<T, A> {
800
        pub(crate) const fn new(t: T) -> Align<T, A> {
801
            Align { t, _a: [] }
802
        }
803
    }
804
805
    /// A `T` which is guaranteed not to satisfy `align_of::<A>()`.
806
    ///
807
    /// It must be the case that `align_of::<T>() < align_of::<A>()` in order
808
    /// for this type to work properly.
809
    #[repr(C)]
810
    pub(crate) struct ForceUnalign<T: Unaligned, A> {
811
        // The outer struct is aligned to `A`, and, thanks to `repr(C)`, `t` is
812
        // placed at the minimum offset that guarantees its alignment. If
813
        // `align_of::<T>() < align_of::<A>()`, then that offset will be
814
        // guaranteed *not* to satisfy `align_of::<A>()`.
815
        //
816
        // Note that we need `T: Unaligned` in order to guarantee that there is
817
        // no padding between `_u` and `t`.
818
        _u: u8,
819
        pub(crate) t: T,
820
        _a: [A; 0],
821
    }
822
823
    impl<T: Unaligned, A> ForceUnalign<T, A> {
824
        pub(crate) fn new(t: T) -> ForceUnalign<T, A> {
825
            ForceUnalign { _u: 0, t, _a: [] }
826
        }
827
    }
828
    // A `u64` with alignment 8.
829
    //
830
    // Though `u64` has alignment 8 on some platforms, it's not guaranteed. By
831
    // contrast, `AU64` is guaranteed to have alignment 8 on all platforms.
832
    #[derive(
833
        KnownLayout,
834
        Immutable,
835
        FromBytes,
836
        IntoBytes,
837
        Eq,
838
        PartialEq,
839
        Ord,
840
        PartialOrd,
841
        Default,
842
        Debug,
843
        Copy,
844
        Clone,
845
    )]
846
    #[repr(C, align(8))]
847
    pub(crate) struct AU64(pub(crate) u64);
848
849
    impl AU64 {
850
        // Converts this `AU64` to bytes using this platform's endianness.
851
        pub(crate) fn to_bytes(self) -> [u8; 8] {
852
            crate::transmute!(self)
853
        }
854
    }
855
856
    impl Display for AU64 {
857
        #[cfg_attr(
858
            all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
859
            coverage(off)
860
        )]
861
        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
862
            Display::fmt(&self.0, f)
863
        }
864
    }
865
}
866
867
#[cfg(test)]
868
mod tests {
869
    use super::*;
870
871
    #[test]
872
    fn test_round_down_to_next_multiple_of_alignment() {
873
        fn alt_impl(n: usize, align: NonZeroUsize) -> usize {
874
            let mul = n / align.get();
875
            mul * align.get()
876
        }
877
878
        for align in [1, 2, 4, 8, 16] {
879
            for n in 0..256 {
880
                let align = NonZeroUsize::new(align).unwrap();
881
                let want = alt_impl(n, align);
882
                let got = round_down_to_next_multiple_of_alignment(n, align);
883
                assert_eq!(got, want, "round_down_to_next_multiple_of_alignment({}, {})", n, align);
884
            }
885
        }
886
    }
887
888
    #[rustversion::since(1.57.0)]
889
    #[test]
890
    #[should_panic]
891
    fn test_round_down_to_next_multiple_of_alignment_zerocopy_panic_in_const_and_vec_try_reserve() {
892
        round_down_to_next_multiple_of_alignment(0, NonZeroUsize::new(3).unwrap());
893
    }
894
    #[test]
895
    fn test_send_sync_phantom_data() {
896
        let x = SendSyncPhantomData::<u8>::default();
897
        let y = x.clone();
898
        assert!(x == y);
899
        assert!(x == SendSyncPhantomData::<u8>::default());
900
    }
901
902
    #[test]
903
    #[allow(clippy::as_conversions)]
904
    fn test_as_address() {
905
        let x = 0u8;
906
        let r = &x;
907
        let mut x_mut = 0u8;
908
        let rm = &mut x_mut;
909
        let p = r as *const u8;
910
        let pm = rm as *mut u8;
911
        let nn = NonNull::new(p as *mut u8).unwrap();
912
913
        assert_eq!(AsAddress::addr(r), p as usize);
914
        assert_eq!(AsAddress::addr(rm), pm as usize);
915
        assert_eq!(AsAddress::addr(p), p as usize);
916
        assert_eq!(AsAddress::addr(pm), pm as usize);
917
        assert_eq!(AsAddress::addr(nn), p as usize);
918
    }
919
}