mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
[asan] Change dynamic alloca instrumentation to only consider allocas that are dominating all exits from function.
Reviewed in http://reviews.llvm.org/D6412 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222991 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
eed2e8bf98
commit
434494196b
@ -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 MappingScale) {
|
||||
|
||||
/// 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 FunctionPass {
|
||||
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 FunctionPass {
|
||||
int LongSize;
|
||||
Type *IntptrTy;
|
||||
ShadowMapping Mapping;
|
||||
DominatorTree *DT;
|
||||
Function *AsanCtorFunction;
|
||||
Function *AsanInitFunction;
|
||||
Function *AsanHandleNoReturnFunc;
|
||||
@ -471,10 +480,11 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
|
||||
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 InstVisitor<FunctionStackPoisoner> {
|
||||
|
||||
// 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 InstVisitor<FunctionStackPoisoner> {
|
||||
// ---------------------- 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 InstVisitor<FunctionStackPoisoner> {
|
||||
} // 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(Function &F) {
|
||||
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::computePartialRzMagic(Value *PartialSize,
|
||||
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());
|
||||
|
@ -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*)
|
||||
|
Loading…
Reference in New Issue
Block a user