[llvm] r222991 - [asan] Change dynamic alloca instrumentation to only consider allocas that are dominating all exits from function.

Yury Gribov y.gribov at samsung.com
Mon Dec 1 00:47:59 PST 2014


Author: ygribov
Date: Mon Dec  1 02:47:58 2014
New Revision: 222991

URL: http://llvm.org/viewvc/llvm-project?rev=222991&view=rev
Log:
[asan] Change dynamic alloca instrumentation to only consider allocas that are dominating all exits from function.

Reviewed in http://reviews.llvm.org/D6412

Added:
    llvm/trunk/test/Instrumentation/AddressSanitizer/undecidable-dynamic-alloca-1.ll
Modified:
    llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Modified: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp?rev=222991&r1=222990&r2=222991&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp Mon Dec  1 02:47:58 2014
@@ -27,6 +27,7 @@
 #include "llvm/IR/CallSite.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InlineAsm.h"
@@ -348,10 +349,15 @@ static size_t RedzoneSizeForScale(int Ma
 
 /// AddressSanitizer: instrument the code in module to find memory bugs.
 struct AddressSanitizer : public FunctionPass {
-  AddressSanitizer() : FunctionPass(ID) {}
+  AddressSanitizer() : FunctionPass(ID) {
+    initializeAddressSanitizerPass(*PassRegistry::getPassRegistry());
+  }
   const char *getPassName() const override {
     return "AddressSanitizerFunctionPass";
   }
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.addRequired<DominatorTreeWrapperPass>();
+  }
   void instrumentMop(Instruction *I, bool UseCalls);
   void instrumentPointerComparisonOrSubtraction(Instruction *I);
   void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
@@ -369,6 +375,8 @@ struct AddressSanitizer : public Functio
   bool doInitialization(Module &M) override;
   static char ID;  // Pass identification, replacement for typeid
 
+  DominatorTree &getDominatorTree() const { return *DT; }
+
  private:
   void initializeCallbacks(Module &M);
 
@@ -380,6 +388,7 @@ struct AddressSanitizer : public Functio
   int LongSize;
   Type *IntptrTy;
   ShadowMapping Mapping;
+  DominatorTree *DT;
   Function *AsanCtorFunction;
   Function *AsanInitFunction;
   Function *AsanHandleNoReturnFunc;
@@ -471,10 +480,11 @@ struct FunctionStackPoisoner : public In
     AllocaInst *AI;
     Value *LeftRzAddr;
     Value *RightRzAddr;
+    bool Poison;
     explicit DynamicAllocaCall(AllocaInst *AI,
                       Value *LeftRzAddr = nullptr,
                       Value *RightRzAddr = nullptr)
-      : AI(AI), LeftRzAddr(LeftRzAddr), RightRzAddr(RightRzAddr)
+      : AI(AI), LeftRzAddr(LeftRzAddr), RightRzAddr(RightRzAddr), Poison(true)
     {}
   };
   SmallVector<DynamicAllocaCall, 1> DynamicAllocaVec;
@@ -520,6 +530,8 @@ struct FunctionStackPoisoner : public In
 
   // Unpoison dynamic allocas redzones.
   void unpoisonDynamicAlloca(DynamicAllocaCall &AllocaCall) {
+    if (!AllocaCall.Poison)
+      return;
     for (auto Ret : RetVec) {
       IRBuilder<> IRBRet(Ret);
       PointerType *Int32PtrTy = PointerType::getUnqual(IRBRet.getInt32Ty());
@@ -605,6 +617,14 @@ struct FunctionStackPoisoner : public In
   // ---------------------- Helpers.
   void initializeCallbacks(Module &M);
 
+  bool doesDominateAllExits(const Instruction *I) const {
+    for (auto Ret : RetVec) {
+      if (!ASan.getDominatorTree().dominates(I, Ret))
+        return false;
+    }
+    return true;
+  }
+
   bool isDynamicAlloca(AllocaInst &AI) const {
     return AI.isArrayAllocation() || !AI.isStaticAlloca();
   }
@@ -634,7 +654,11 @@ struct FunctionStackPoisoner : public In
 }  // namespace
 
 char AddressSanitizer::ID = 0;
-INITIALIZE_PASS(AddressSanitizer, "asan",
+INITIALIZE_PASS_BEGIN(AddressSanitizer, "asan",
+    "AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
+    false, false)
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
+INITIALIZE_PASS_END(AddressSanitizer, "asan",
     "AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
     false, false)
 FunctionPass *llvm::createAddressSanitizerFunctionPass() {
@@ -1354,6 +1378,8 @@ bool AddressSanitizer::runOnFunction(Fun
   DEBUG(dbgs() << "ASAN instrumenting:\n" << F << "\n");
   initializeCallbacks(*F.getParent());
 
+  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+
   // If needed, insert __asan_init before checking for SanitizeAddress attr.
   maybeInsertAsanInitAtFunctionEntry(F);
 
@@ -1825,6 +1851,12 @@ Value *FunctionStackPoisoner::computePar
 void FunctionStackPoisoner::handleDynamicAllocaCall(
     DynamicAllocaCall &AllocaCall) {
   AllocaInst *AI = AllocaCall.AI;
+  if (!doesDominateAllExits(AI)) {
+    // We do not yet handle complex allocas
+    AllocaCall.Poison = false;
+    return;
+  }
+
   IRBuilder<> IRB(AI);
 
   PointerType *Int32PtrTy = PointerType::getUnqual(IRB.getInt32Ty());

Added: llvm/trunk/test/Instrumentation/AddressSanitizer/undecidable-dynamic-alloca-1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/AddressSanitizer/undecidable-dynamic-alloca-1.ll?rev=222991&view=auto
==============================================================================
--- llvm/trunk/test/Instrumentation/AddressSanitizer/undecidable-dynamic-alloca-1.ll (added)
+++ llvm/trunk/test/Instrumentation/AddressSanitizer/undecidable-dynamic-alloca-1.ll Mon Dec  1 02:47:58 2014
@@ -0,0 +1,23 @@
+; Test that undecidable dynamic allocas are skipped by ASan.
+
+; RUN: opt < %s -asan -asan-module -asan-instrument-allocas=1 -S | FileCheck %s
+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"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @g(i64 %n) sanitize_address {
+entry:
+  %cmp = icmp sgt i64 %n, 100
+  br i1 %cmp, label %do_alloca, label %done
+
+do_alloca:
+; CHECK-NOT: store i32 -892679478
+  %0 = alloca i8, i64 %n, align 1
+  call void @f(i8* %0)
+  br label %done
+
+done:
+  ret void
+}
+
+declare void @f(i8*)
+





More information about the llvm-commits mailing list