mirror of https://github.com/rust-lang/rust.git
Rollup merge of #104110 - krasimirgg:msan-16, r=nagisa
prevent uninitialized access in black_box for zero-sized-types Don't read the pointer location in black_box for zero sized types, just emit a memory clobber instead. Addresses https://github.com/rust-lang/rust/issues/103304 when rust is build against LLVM at HEAD. Zulip thread: https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm/topic/.28with.20llvm.20at.20HEAD.29.3A.20msan.20error.20in.20core.3A.3Ahint.3A.3Ablack_box
This commit is contained in:
commit
798815aec5
|
@ -340,17 +340,26 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
|
||||
sym::black_box => {
|
||||
args[0].val.store(self, result);
|
||||
|
||||
let result_val_span = [result.llval];
|
||||
// We need to "use" the argument in some way LLVM can't introspect, and on
|
||||
// targets that support it we can typically leverage inline assembly to do
|
||||
// this. LLVM's interpretation of inline assembly is that it's, well, a black
|
||||
// box. This isn't the greatest implementation since it probably deoptimizes
|
||||
// more than we want, but it's so far good enough.
|
||||
//
|
||||
// For zero-sized types, the location pointed to by the result may be
|
||||
// uninitialized. Do not "use" the result in this case; instead just clobber
|
||||
// the memory.
|
||||
let (constraint, inputs): (&str, &[_]) = if result.layout.is_zst() {
|
||||
("~{memory}", &[])
|
||||
} else {
|
||||
("r,~{memory}", &result_val_span)
|
||||
};
|
||||
crate::asm::inline_asm_call(
|
||||
self,
|
||||
"",
|
||||
"r,~{memory}",
|
||||
&[result.llval],
|
||||
constraint,
|
||||
inputs,
|
||||
self.type_void(),
|
||||
true,
|
||||
false,
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// needs-sanitizer-support
|
||||
// needs-sanitizer-memory
|
||||
//
|
||||
// revisions: unoptimized optimized
|
||||
//
|
||||
// [optimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O
|
||||
// [unoptimized]compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins
|
||||
//
|
||||
// run-pass
|
||||
//
|
||||
// This test case intentionally limits the usage of the std,
|
||||
// since it will be linked with an uninstrumented version of it.
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(start)]
|
||||
#![allow(invalid_value)]
|
||||
|
||||
use std::hint::black_box;
|
||||
|
||||
fn calling_black_box_on_zst_ok() {
|
||||
// It's OK to call black_box on a value of a zero-sized type, even if its
|
||||
// underlying the memory location is uninitialized. For non-zero-sized types,
|
||||
// this would be an MSAN error.
|
||||
let zst = ();
|
||||
black_box(zst);
|
||||
}
|
||||
|
||||
#[start]
|
||||
fn main(_: isize, _: *const *const u8) -> isize {
|
||||
calling_black_box_on_zst_ok();
|
||||
0
|
||||
}
|
Loading…
Reference in New Issue