From e1c8bc63283295ce79b45026d778db8f9ab9b7bf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 12 Jul 2022 09:41:47 -0400 Subject: [PATCH 1/2] mem::uninitialized: mitigate many incorrect uses of this function --- core/src/lib.rs | 1 + core/src/mem/mod.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/core/src/lib.rs b/core/src/lib.rs index bd256cec8..b4c9f443c 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -163,6 +163,7 @@ #![feature(allow_internal_unstable)] #![feature(associated_type_bounds)] #![feature(auto_traits)] +#![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic_equal_alignment)] #![feature(const_fn_floating_point_arithmetic)] diff --git a/core/src/mem/mod.rs b/core/src/mem/mod.rs index ecd2b75ae..1e665896a 100644 --- a/core/src/mem/mod.rs +++ b/core/src/mem/mod.rs @@ -683,7 +683,15 @@ pub unsafe fn uninitialized() -> T { // SAFETY: the caller must guarantee that an uninitialized value is valid for `T`. unsafe { intrinsics::assert_uninit_valid::(); - MaybeUninit::uninit().assume_init() + let mut val = MaybeUninit::::uninit(); + + // Fill memory with 0x01, as an imperfect mitigation for old code that uses this function on + // bool, nonnull, and noundef types. But don't do this if we actively want to detect UB. + if !cfg!(any(miri, sanitize = "memory")) { + val.as_mut_ptr().write_bytes(0x01, 1); + } + + val.assume_init() } } From 36c458de0f8e8eb3acb53141816f98f2830fac6b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 12 Jul 2022 11:56:35 -0400 Subject: [PATCH 2/2] mention mitigation in the docs --- core/src/mem/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/mem/mod.rs b/core/src/mem/mod.rs index 1e665896a..31f44e371 100644 --- a/core/src/mem/mod.rs +++ b/core/src/mem/mod.rs @@ -654,6 +654,8 @@ pub unsafe fn zeroed() -> T { /// produce a value of type `T`, while doing nothing at all. /// /// **This function is deprecated.** Use [`MaybeUninit`] instead. +/// It also might be slower than using `MaybeUninit` due to mitigations that were put in place to +/// limit the potential harm caused by incorrect use of this function in legacy code. /// /// The reason for deprecation is that the function basically cannot be used /// correctly: it has the same effect as [`MaybeUninit::uninit().assume_init()`][uninit].