Skip to content

Commit

Permalink
Rollup merge of rust-lang#104110 - krasimirgg:msan-16, r=nagisa
Browse files Browse the repository at this point in the history
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  rust-lang#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
  • Loading branch information
Manishearth committed Nov 11, 2022
2 parents 7658f0e + 0e0bcd9 commit 55f07c7
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
15 changes: 12 additions & 3 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
32 changes: 32 additions & 0 deletions src/test/ui/sanitize/memory-passing.rs
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 55f07c7

Please sign in to comment.