pub(crate) fn minimally_init(buf: &mut [MaybeUninit<u8>]) -> &mut [u8] ⓘExpand description
When we only care about writing to a slice but &mut [u8] grants the
read capability and reading would be UB, this function does the minimum
writing to make the slice have arbitrary but fixed-value bytes. This
maintains correct boundary between unsafe and safe in terms of UB
avoidance resposibility even though we don’t actually perform reads.
The caller must not rely on any byte in the slice that was already
initialized to retain its value after this function returns.
The point of wishing to not to contaminate all places with
&mut [MaybeUninit<u8>] is that &mut [u8] interacts better with
core::simd in a way that doesn’t require unsafe in more places.
Note that the caller has to overwrite the exposed arbitrary but fixed-value
bytes to avoid information disclosure (somewhat analogously to reusing an
intermediate buffer created without any unsafe). This function is not
unsafe, because this function does not let the caller to experience UB.
Letting &mut [MaybeUninit<u8>] show up in more places in the crate internals
would not change the information disclosure risk in case there’s a bug in
the tracking of how much has been written. Either way, the tracking of how
much has been written has to actually work, but it has a very good track
record of working.
On M3 Pro, we could just zero-initialize every byte without a notable performance penalty, but on Zen 3 and Skylake, zeroing all bytes carries a measurable penalty (in some cases only; depending on details of subsequent writes!) but zeroing the first byte of every page does not carry this perf penalty compared to not initializing anything (at least when the slice is reasonable-sized relative to what meaningful data end up written into it later).