summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp15
-rw-r--r--llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll36
2 files changed, 50 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 4c827aca20e..d73907c5aca 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -884,6 +884,7 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
};
SmallVector<AllocaPoisonCall, 8> DynamicAllocaPoisonCallVec;
SmallVector<AllocaPoisonCall, 8> StaticAllocaPoisonCallVec;
+ bool HasUntracedLifetimeIntrinsic = false;
SmallVector<AllocaInst *, 1> DynamicAllocaVec;
SmallVector<IntrinsicInst *, 1> StackRestoreVec;
@@ -918,6 +919,14 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
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();
@@ -1040,8 +1049,12 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
// Find alloca instruction that corresponds to llvm.lifetime argument.
AllocaInst *AI =
llvm::findAllocaForValue(II.getArgOperand(1), AllocaForValue);
+ if (!AI) {
+ HasUntracedLifetimeIntrinsic = true;
+ return;
+ }
// We're interested only in allocas we can handle.
- if (!AI || !ASan.isInterestingAlloca(*AI))
+ if (!ASan.isInterestingAlloca(*AI))
return;
bool DoPoison = (ID == Intrinsic::lifetime_end);
AllocaPoisonCall APC = {&II, AI, SizeValue, DoPoison};
diff --git a/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll b/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll
index 56a63110a84..5523da63d37 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll
@@ -209,6 +209,42 @@ entry:
; 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)
OpenPOWER on IntegriCloud