Skip to content

Commit 68470c1

Browse files
committed
Detect use of MemorySanitizer without using Nightly-only features
This allows msan detection to "just-work" whenever someone passes `-Zsanitizer=memory`. Users no longer need to do any `getrandom`-specific configuration. This will also continue working once rust-lang/rust#123615 is merged which stabilizes some sanitizers (but not MemorySanitizer). This is the approch taken by other low-level crates: - [`parking_lot_core`](https://github.com/Amanieu/parking_lot/blob/ca920b31312839013b4455aba1d53a4aede21b2f/core/build.rs) - [`crossbeam-utils`](https://github.com/crossbeam-rs/crossbeam/blob/00283fb1818174c25b02d7f1c883c5e19f8506a4/crossbeam-utils/build.rs#L42) The only downside is that this adds a build-script, but it's as small as possible, doesn't seem to impact build times, and is only a temporary workaround. Signed-off-by: Joe Richey <[email protected]>
1 parent 12c9f80 commit 68470c1

File tree

5 files changed

+21
-14
lines changed

5 files changed

+21
-14
lines changed

.github/workflows/tests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ jobs:
140140
toolchain: nightly-2024-10-08
141141
components: rust-src
142142
- env:
143-
RUSTFLAGS: -Dwarnings -Zsanitizer=memory --cfg getrandom_sanitize
143+
RUSTFLAGS: -Dwarnings -Zsanitizer=memory
144144
# `--all-targets` is used to skip doc tests which currently fail linking
145145
run: cargo test -Zbuild-std --target=x86_64-unknown-linux-gnu --all-targets
146146

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ rustc-dep-of-std = ["dep:compiler_builtins", "dep:core"]
8181
level = "warn"
8282
check-cfg = [
8383
'cfg(getrandom_backend, values("custom", "rdrand", "rndr", "linux_getrandom", "linux_rustix", "wasm_js", "esp_idf"))',
84-
'cfg(getrandom_sanitize)',
84+
'cfg(getrandom_msan)',
8585
'cfg(getrandom_test_linux_fallback)',
8686
'cfg(getrandom_test_netbsd_fallback)',
8787
]

README.md

+8-7
Original file line numberDiff line numberDiff line change
@@ -267,15 +267,16 @@ our code should correctly handle it and return an error, e.g.
267267

268268
## Sanitizer support
269269

270-
If your code uses [`fill_uninit`] and you enable memory sanitization
271-
(i.e. `-Zsanitizer=memory`), you need to pass the `getrandom_sanitize`
272-
configuration flag to enable unpoisoning of the destination buffer
273-
filled by `fill_uninit`.
270+
If your code uses [`fill_uninit`] and you enable
271+
[MemorySanitizer](https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#memorysanitizer)
272+
(i.e. `-Zsanitizer=memory`), we will automatically handle unpoisoning
273+
of the destination buffer filled by `fill_uninit`.
274274

275-
For example, it can be done as follows (requires a Nightly compiler):
275+
The following command runs all our tests with MemorySanitizer
276+
(requires a Nightly compiler):
276277
```sh
277-
RUSTFLAGS="-Zsanitizer=memory --cfg getrandom_sanitize" \
278-
cargo test -Zbuild-std --target=x86_64-unknown-linux-gnu
278+
RUSTFLAGS="-Zsanitizer=memory" cargo test \
279+
-Zbuild-std --target=x86_64-unknown-linux-gnu --all-targets
279280
```
280281

281282
## Minimum Supported Rust Version

build.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Automatically detect cfg(sanitize = "memory") even if cfg(sanitize) isn't
2+
// supported. Build scripts get cfg() info, even if the cfg is unstable.
3+
fn main() {
4+
println!("cargo:rerun-if-changed=build.rs");
5+
let santizers = std::env::var("CARGO_CFG_SANITIZE").unwrap_or_default();
6+
if santizers.contains("memory") {
7+
println!("cargo:rustc-cfg=getrandom_msan");
8+
}
9+
}

src/lib.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#![doc = include_str!("../README.md")]
1111
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
1212
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
13-
#![cfg_attr(getrandom_sanitize, feature(cfg_sanitize))]
1413
#![deny(
1514
clippy::cast_lossless,
1615
clippy::cast_possible_truncation,
@@ -99,17 +98,15 @@ pub fn fill_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error> {
9998
backends::fill_inner(dest)?;
10099
}
101100

102-
#[cfg(getrandom_sanitize)]
103-
#[cfg(sanitize = "memory")]
101+
#[cfg(getrandom_msan)]
104102
extern "C" {
105103
fn __msan_unpoison(a: *mut core::ffi::c_void, size: usize);
106104
}
107105

108106
// SAFETY: `dest` has been fully initialized by `imp::fill_inner`
109107
// since it returned `Ok`.
110108
Ok(unsafe {
111-
#[cfg(getrandom_sanitize)]
112-
#[cfg(sanitize = "memory")]
109+
#[cfg(getrandom_msan)]
113110
__msan_unpoison(dest.as_mut_ptr().cast(), dest.len());
114111

115112
util::slice_assume_init_mut(dest)

0 commit comments

Comments
 (0)