about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_codegen_llvm/builder.rs15
-rw-r--r--src/rustllvm/PassWrapper.cpp3
-rw-r--r--src/test/ui/sanitizer-use-after-scope.rs18
3 files changed, 31 insertions, 5 deletions
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 357b0b6c451..c59b81eb4cc 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -7,7 +7,7 @@ use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 use libc::{c_char, c_uint};
 use log::debug;
-use rustc::session::config;
+use rustc::session::config::{self, Sanitizer};
 use rustc::ty::layout::{self, Align, Size, TyLayout};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_codegen_ssa::base::to_immediate;
@@ -1232,12 +1232,19 @@ impl Builder<'a, 'll, 'tcx> {
     }
 
     fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
-        if self.cx.sess().opts.optimize == config::OptLevel::No {
+        let size = size.bytes();
+        if size == 0 {
             return;
         }
 
-        let size = size.bytes();
-        if size == 0 {
+        let opts = &self.cx.sess().opts;
+        let emit = match opts.debugging_opts.sanitizer {
+            // Some sanitizer use lifetime intrinsics. When they are in use,
+            // emit lifetime intrinsics regardless of optimization level.
+            Some(Sanitizer::Address) | Some(Sanitizer::Memory) => true,
+            _ => opts.optimize != config::OptLevel::No,
+        };
+        if !emit {
             return;
         }
 
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index eaa845a279f..fad70369807 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -87,8 +87,9 @@ extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
 
 extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) {
   const bool CompileKernel = false;
+  const bool UseAfterScope = true;
 
-  return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover));
+  return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope));
 }
 
 extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) {
diff --git a/src/test/ui/sanitizer-use-after-scope.rs b/src/test/ui/sanitizer-use-after-scope.rs
new file mode 100644
index 00000000000..6a2067e157a
--- /dev/null
+++ b/src/test/ui/sanitizer-use-after-scope.rs
@@ -0,0 +1,18 @@
+// needs-sanitizer-support
+// only-x86_64
+//
+// compile-flags: -Zsanitizer=address
+// run-fail
+// error-pattern: ERROR: AddressSanitizer: stack-use-after-scope
+
+static mut P: *mut usize = std::ptr::null_mut();
+
+fn main() {
+    unsafe {
+        {
+            let mut x = 0;
+            P = &mut x;
+        }
+        std::ptr::write_volatile(P, 123);
+    }
+}