Index: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -745,7 +745,8 @@ return; // Find alloca instruction that corresponds to llvm.lifetime argument. AllocaInst *AI = findAllocaForValue(II.getArgOperand(1)); - if (!AI) return; + if (!AI || !ASan.isInterestingAlloca(*AI)) + return; bool DoPoison = (ID == Intrinsic::lifetime_end); AllocaPoisonCall APC = {&II, AI, SizeValue, DoPoison}; AllocaPoisonCallVec.push_back(APC); @@ -1984,13 +1985,21 @@ assert(AllocaVec.size() > 0 || DynamicAllocaVec.size() > 0); // Insert poison calls for lifetime intrinsics for alloca. - bool HavePoisonedAllocas = false; + bool HavePoisonedStaticAllocas = false; for (const auto &APC : AllocaPoisonCallVec) { assert(APC.InsBefore); assert(APC.AI); + assert(ASan.isInterestingAlloca(*APC.AI)); + bool IsDynamicAlloca = ASan.isDynamicAlloca(*APC.AI); + if (!ClInstrumentAllocas && IsDynamicAlloca) + continue; + IRBuilder<> IRB(APC.InsBefore); poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison); - HavePoisonedAllocas |= APC.DoPoison; + // Dynamic allocas will be unpoisoned unconditionally below in + // unpoisonDynamicAllocas. + // Flag that we need unpoison static allocas. + HavePoisonedStaticAllocas |= (APC.DoPoison && !IsDynamicAlloca); } if (ClInstrumentAllocas && DynamicAllocaVec.size() > 0) { @@ -2137,7 +2146,7 @@ poisonRedZones(L.ShadowBytes, IRB, ShadowBase, true); auto UnpoisonStack = [&](IRBuilder<> &IRB) { - if (HavePoisonedAllocas) { + if (HavePoisonedStaticAllocas) { // If we poisoned some allocas in llvm.lifetime analysis, // unpoison whole stack frame now. poisonAlloca(LocalStackBase, LocalStackSize, IRB, false); Index: llvm/trunk/test/Instrumentation/AddressSanitizer/lifetime.ll =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/lifetime.ll +++ llvm/trunk/test/Instrumentation/AddressSanitizer/lifetime.ll @@ -1,5 +1,6 @@ ; Test hanlding of llvm.lifetime intrinsics. ; RUN: opt < %s -asan -asan-module -asan-use-after-scope -asan-use-after-return=0 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -asan-use-after-scope -asan-use-after-return=0 -asan-instrument-allocas=0 -S | FileCheck %s --check-prefix=CHECK-NO-DYNAMIC target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -47,8 +48,10 @@ call void @llvm.lifetime.start(i64 40, i8* %arr.ptr) store volatile i8 0, i8* %arr.ptr ; CHECK: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 40) + ; CHECK-NO-DYNAMIC-NOT: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 40) call void @llvm.lifetime.end(i64 40, i8* %arr.ptr) ; CHECK: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 40) + ; CHECK-NO-DYNAMIC-NOT: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 40) ; One more lifetime start/end for the same variable %i. call void @llvm.lifetime.start(i64 4, i8* %i.ptr) @@ -87,3 +90,20 @@ ; CHECK: ret void ret void } + +define void @zero_sized(i64 %a) #0 { +; CHECK-LABEL: define void @zero_sized(i64 %a) + +entry: + %a.addr = alloca i64, align 8 + %b = alloca [0 x i8], align 1 + store i64 %a, i64* %a.addr, align 8 + %0 = bitcast [0 x i8]* %b to i8* + call void @llvm.lifetime.start(i64 0, i8* %0) #2 + ; CHECK-NOT: call void @__asan_unpoison_stack_memory + %1 = bitcast [0 x i8]* %b to i8* + call void @llvm.lifetime.end(i64 0, i8* %1) #2 + ; CHECK-NOT: call void @__asan_poison_stack_memory + + ret void +}