Skip to content

Commit 08a1c56

Browse files
committed
Detect use-after-scope bugs with AddressSanitizer
Enable use-after-scope checks by default when using AddressSanitizer. They allow to detect incorrect use of stack objects after their scope have already ended. The detection is based on LLVM lifetime intrinsics. To facilitate the use of this functionality, the lifetime intrinsics are now emitted regardless of optimization level if enabled sanitizer makes use of them.
1 parent 1d5f6d4 commit 08a1c56

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

src/librustc_codegen_llvm/builder.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::type_of::LayoutLlvmExt;
77
use crate::value::Value;
88
use libc::{c_char, c_uint};
99
use log::debug;
10-
use rustc::session::config;
10+
use rustc::session::config::{self, Sanitizer};
1111
use rustc::ty::layout::{self, Align, Size, TyLayout};
1212
use rustc::ty::{self, Ty, TyCtxt};
1313
use rustc_codegen_ssa::base::to_immediate;
@@ -1232,12 +1232,19 @@ impl Builder<'a, 'll, 'tcx> {
12321232
}
12331233

12341234
fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
1235-
if self.cx.sess().opts.optimize == config::OptLevel::No {
1235+
let size = size.bytes();
1236+
if size == 0 {
12361237
return;
12371238
}
12381239

1239-
let size = size.bytes();
1240-
if size == 0 {
1240+
let opts = &self.cx.sess().opts;
1241+
let emit = match opts.debugging_opts.sanitizer {
1242+
// Some sanitizer use lifetime intrinsics. When they are in use,
1243+
// emit lifetime intrinsics regardless of optimization level.
1244+
Some(Sanitizer::Address) | Some(Sanitizer::Memory) => true,
1245+
_ => opts.optimize != config::OptLevel::No,
1246+
};
1247+
if !emit {
12411248
return;
12421249
}
12431250

src/rustllvm/PassWrapper.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,9 @@ extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
8787

8888
extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) {
8989
const bool CompileKernel = false;
90+
const bool UseAfterScope = true;
9091

91-
return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover));
92+
return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope));
9293
}
9394

9495
extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) {
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// needs-sanitizer-support
2+
// only-x86_64
3+
//
4+
// compile-flags: -Zsanitizer=address
5+
// run-fail
6+
// error-pattern: ERROR: AddressSanitizer: stack-use-after-scope
7+
8+
static mut P: *mut usize = std::ptr::null_mut();
9+
10+
fn main() {
11+
unsafe {
12+
{
13+
let mut x = 0;
14+
P = &mut x;
15+
}
16+
std::ptr::write_volatile(P, 123);
17+
}
18+
}

0 commit comments

Comments
 (0)