[PATCH] D60686: Asan use-after-scope: don't poison allocas if there were untraced lifetime intrinsics in the function (PR41481)

Hans Wennborg via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 15 04:42:50 PDT 2019


hans created this revision.
hans added reviewers: kcc, eugenis, vitalybuka.
Herald added a subscriber: hiraditya.
Herald added a project: LLVM.

If there are any intrinsics that cannot be traced back to an alloca, we might have missed the start of a variable's scope, leading to false error reports if the variable is poisoned at function entry. Instead, if there are some intrinsics that can't be traced, fail safe and don't poison the variables in that function.


https://reviews.llvm.org/D60686

Files:
  llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
  llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll


Index: llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll
===================================================================
--- llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll
+++ llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll
@@ -209,6 +209,42 @@
   ; CHECK: ret void
 }
 
+declare void @foo(i32*)
+define void @PR41481(i1 %b) sanitize_address {
+; CHECK-LABEL: @PR41481
+entry:
+  %p1 = alloca i32
+  %p2 = alloca i32
+  %q1 = bitcast i32* %p1 to i8*
+  %q2 = bitcast i32* %p2 to i8*
+  br label %bb1
+
+  ; Since we cannot account for all lifetime intrinsics in this function, we
+  ; might have missed a lifetime.start one and therefore shouldn't poison the
+  ; allocas at function entry.
+  ; ENTRY: store i64 -935356719533264399
+  ; ENTRY-UAS: store i64 -935356719533264399
+
+bb1:
+  %p = select i1 %b, i32* %p1, i32* %p2
+  %q = select i1 %b, i8*  %q1, i8*  %q2
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* %q)
+  call void @foo(i32* %p)
+  br i1 %b, label %bb2, label %bb3
+
+bb2:
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* %q1)
+  br label %end
+
+bb3:
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* %q2)
+  br label %end
+
+end:
+  ret void
+}
+
+
 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
 
Index: llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
===================================================================
--- llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -884,6 +884,7 @@
   };
   SmallVector<AllocaPoisonCall, 8> DynamicAllocaPoisonCallVec;
   SmallVector<AllocaPoisonCall, 8> StaticAllocaPoisonCallVec;
+  bool HasUntracedLifetimeIntrinsic = false;
 
   SmallVector<AllocaInst *, 1> DynamicAllocaVec;
   SmallVector<IntrinsicInst *, 1> StackRestoreVec;
@@ -918,6 +919,14 @@
 
     initializeCallbacks(*F.getParent());
 
+    if (HasUntracedLifetimeIntrinsic) {
+      // If there are lifetime intrinsics which couldn't be traced back to an
+      // alloca, we may not know exactly when a variable enters scope, and
+      // therefore should "fail safe" by not poisoning them.
+      StaticAllocaPoisonCallVec.clear();
+      DynamicAllocaPoisonCallVec.clear();
+    }
+
     processDynamicAllocas();
     processStaticAllocas();
 
@@ -1039,7 +1048,11 @@
       return;
     // Find alloca instruction that corresponds to llvm.lifetime argument.
     AllocaInst *AI = findAllocaForValue(II.getArgOperand(1));
-    if (!AI || !ASan.isInterestingAlloca(*AI))
+    if (!AI) {
+      HasUntracedLifetimeIntrinsic = true;
+      return;
+    }
+    if (!ASan.isInterestingAlloca(*AI))
       return;
     bool DoPoison = (ID == Intrinsic::lifetime_end);
     AllocaPoisonCall APC = {&II, AI, SizeValue, DoPoison};


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D60686.195133.patch
Type: text/x-patch
Size: 2887 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190415/eac7e2dc/attachment.bin>


More information about the llvm-commits mailing list