Coverage Report

Created: 2026-07-25 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zeroize-1.9.0/src/barrier.rs
Line
Count
Source
1
/// Observe the referenced data and prevent the compiler from removing previous writes to it.
2
///
3
/// This function acts like [`core::hint::black_box`] but takes a reference and
4
/// does not return the passed value.
5
///
6
/// It's implemented using the [`core::arch::asm!`] macro on target arches where `asm!` is stable,
7
/// i.e. `aarch64`, `arm`, `arm64ec`, `loongarch64`, `riscv32`, `riscv64`, `s390x`, `x86`, and
8
/// `x86_64`.
9
///
10
/// On all other targets it's implemented using [`core::hint::black_box`] and custom `black_box`
11
/// implemented using `#[inline(never)]` and `read_volatile`.
12
///
13
/// # Examples
14
/// ```
15
/// use core::num::NonZeroU32;
16
/// use zeroize::{ZeroizeOnDrop, zeroize_flat_type};
17
///
18
/// # type ThirdPartyType = u32;
19
///
20
/// struct DataToZeroize {
21
///     buf: [u8; 32],
22
///     // `ThirdPartyType` can be a type with private fields
23
///     // defined in a third-party crate and which does not implement
24
///     // `Zeroize` or zeroization on drop.
25
///     data: ThirdPartyType,
26
///     pos: NonZeroU32,
27
/// }
28
///
29
/// struct SomeMoreFlatData(u64);
30
///
31
/// impl Drop for DataToZeroize {
32
///     fn drop(&mut self) {
33
///         self.buf = [0u8; 32];
34
///         self.data = ThirdPartyType::default();
35
///         self.pos = NonZeroU32::new(32).unwrap();
36
///         zeroize::optimization_barrier(self);
37
///     }
38
/// }
39
///
40
/// impl zeroize::ZeroizeOnDrop for DataToZeroize {}
41
///
42
/// let mut data = DataToZeroize {
43
///     buf: [3u8; 32],
44
///     data: ThirdPartyType::default(),
45
///     pos: NonZeroU32::new(32).unwrap(),
46
/// };
47
///
48
/// // data gets zeroized when dropped
49
/// ```
50
///
51
/// Note that erasure of `ThirdPartyType` demonstrated above can be fragile if it contains
52
/// `MaybeUninit` or `union` data. It also does not perform erasure of types like `Box` or `Vec`.
53
0
pub fn optimization_barrier<T: ?Sized>(val: &T) {
54
    #[cfg(all(
55
        not(miri),
56
        any(
57
            target_arch = "aarch64",
58
            target_arch = "arm",
59
            target_arch = "arm64ec",
60
            target_arch = "loongarch64",
61
            target_arch = "riscv32",
62
            target_arch = "riscv64",
63
            target_arch = "s390x",
64
            target_arch = "x86",
65
            target_arch = "x86_64",
66
        )
67
    ))]
68
0
    unsafe {
69
0
        core::arch::asm!(
70
0
            "# {}",
71
0
            in(reg) core::ptr::from_ref::<T>(val).cast::<()>(),
72
0
            options(readonly, preserves_flags, nostack),
73
0
        );
74
0
    }
75
    #[cfg(not(all(
76
        not(miri),
77
        any(
78
            target_arch = "aarch64",
79
            target_arch = "arm",
80
            target_arch = "arm64ec",
81
            target_arch = "loongarch64",
82
            target_arch = "riscv32",
83
            target_arch = "riscv64",
84
            target_arch = "s390x",
85
            target_arch = "x86",
86
            target_arch = "x86_64",
87
        )
88
    )))]
89
    {
90
        /// Custom version of `core::hint::black_box` implemented using
91
        /// `#[inline(never)]` and `read_volatile`.
92
        #[inline(never)]
93
        fn custom_black_box(p: *const u8) {
94
            let _ = unsafe { core::ptr::read_volatile(p) };
95
        }
96
97
        core::hint::black_box(val);
98
        if size_of_val(val) > 0 {
99
            custom_black_box(core::ptr::from_ref(val).cast::<u8>());
100
        }
101
    }
102
0
}
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<u32>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<u16>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<u64>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<i8>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<u8>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<isize>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<usize>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<i32>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<u32>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<i128>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<u128>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<i16>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<u16>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<i64>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<core::num::nonzero::NonZero<u64>>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<[core::mem::maybe_uninit::MaybeUninit<u8>]>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<[u8]>
Unexecuted instantiation: zeroize::barrier::optimization_barrier::<u8>