Coverage Report

Created: 2025-10-28 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/getrandom-0.3.4/src/backends/sanitizer.rs
Line
Count
Source
1
use core::mem::MaybeUninit;
2
3
/// Unpoisons `buf` if MSAN support is enabled.
4
///
5
/// Most backends do not need to unpoison their output. Rust language- and
6
/// library- provided functionality unpoisons automatically. Similarly, libc
7
/// either natively supports MSAN and/or MSAN hooks libc-provided functions
8
/// to unpoison outputs on success. Only when all of these things are
9
/// bypassed do we need to do it ourselves.
10
///
11
/// The call to unpoison should be done as close to the write as possible.
12
/// For example, if the backend partially fills the output buffer in chunks,
13
/// each chunk should be unpoisoned individually. This way, the correctness of
14
/// the chunking logic can be validated (in part) using MSAN.
15
0
pub unsafe fn unpoison(buf: &mut [MaybeUninit<u8>]) {
16
    cfg_if! {
17
        if #[cfg(getrandom_msan)] {
18
            extern "C" {
19
                fn __msan_unpoison(a: *mut core::ffi::c_void, size: usize);
20
            }
21
            let a = buf.as_mut_ptr().cast();
22
            let size = buf.len();
23
            #[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this.
24
            unsafe {
25
                __msan_unpoison(a, size);
26
            }
27
        } else {
28
0
            let _ = buf;
29
        }
30
    }
31
0
}
32
33
/// Interprets the result of the `getrandom` syscall of Linux, unpoisoning any
34
/// written part of `buf`.
35
///
36
/// `buf` must be the output buffer that was originally passed to the `getrandom`
37
/// syscall.
38
///
39
/// `ret` must be the result returned by `getrandom`. If `ret` is negative or
40
/// larger than the length of `buf` then nothing is done.
41
///
42
/// Memory Sanitizer only intercepts `getrandom` on this condition (from its
43
/// source code):
44
/// ```c
45
/// #define SANITIZER_INTERCEPT_GETRANDOM \
46
///   ((SI_LINUX && __GLIBC_PREREQ(2, 25)) || SI_FREEBSD || SI_SOLARIS)
47
/// ```
48
/// So, effectively, we have to assume that it is never intercepted on Linux.
49
#[cfg(any(target_os = "android", target_os = "linux"))]
50
0
pub unsafe fn unpoison_linux_getrandom_result(buf: &mut [MaybeUninit<u8>], ret: isize) {
51
0
    if let Ok(bytes_written) = usize::try_from(ret) {
52
0
        if let Some(written) = buf.get_mut(..bytes_written) {
53
            #[allow(unused_unsafe)] // TODO(MSRV 1.65): Remove this.
54
            unsafe {
55
0
                unpoison(written)
56
            }
57
0
        }
58
0
    }
59
0
}