Report the null deref warning through diagnostic engine.

This commit is contained in:
Baozeng Ding 2013-07-27 21:11:21 +03:00 committed by sftnight
parent 6b26c3a415
commit 8e17b5e93e
5 changed files with 53 additions and 27 deletions

View File

@ -82,7 +82,7 @@ namespace cling {
// Register the IR Transformers
m_IRTransformers.push_back(new IRDumper());
m_IRTransformers.push_back(new NullDerefProtectionTransformer());
m_IRTransformers.push_back(new NullDerefProtectionTransformer(TheSema));
}
void IncrementalParser::Initialize() {

View File

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author: Vassil Vassilev <vvasielv@cern.ch>
// author: Vassil Vassilev <vvasilev@cern.ch>
// author: Baozeng Ding <sploving1@gmail.com>
//------------------------------------------------------------------------------
@ -12,6 +12,8 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Mangle.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Constants.h"
@ -22,9 +24,11 @@
extern "C" {
int printf(const char *...);
int getchar(void);
bool shouldProceed() {
bool shouldProceed(void *S) {
int input;
printf("Warning: you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]\n");
clang::Sema *Sem = (clang::Sema *)S;
clang::DiagnosticsEngine &Diag = Sem->getDiagnostics();
Diag.Report(Diag.getCurrentDiagLoc(), clang::diag::warn_null_ptr_deref);
input = getchar();
getchar();
if (input == 'y' || input == 'Y') return false;
@ -32,10 +36,12 @@ extern "C" {
}
}
using namespace clang;
namespace cling {
NullDerefProtectionTransformer::NullDerefProtectionTransformer()
: TransactionTransformer(/*Sema=*/0), FailBB(0), Builder(0), Inst(0) {}
NullDerefProtectionTransformer::NullDerefProtectionTransformer(Sema *S)
: TransactionTransformer(S), FailBB(0), Builder(0), Inst(0) {}
NullDerefProtectionTransformer::~NullDerefProtectionTransformer()
{}
@ -80,30 +86,44 @@ namespace cling {
}
// Find the function in the module.
llvm::Function* F
= getTransaction()->getModule()->getFunction(mangledName);
llvm::Function* F = getTransaction()->getModule()->getFunction(mangledName);
if (F)
runOnFunction(*F);
}
llvm::BasicBlock* NullDerefProtectionTransformer::getTrapBB() {
llvm::Function *Fn = Inst->getParent()->getParent();
llvm::Module *Md = Fn->getParent();
llvm::Function* Fn = Inst->getParent()->getParent();
llvm::Module* Md = Fn->getParent();
llvm::LLVMContext& ctx = Fn->getContext();
llvm::BasicBlock::iterator PreInsertInst = Builder->GetInsertPoint();
FailBB = llvm::BasicBlock::Create(ctx, "FailBlock", Fn);
Builder->SetInsertPoint(FailBB);
llvm::FunctionType* FTy = llvm::FunctionType::get(llvm::Type::getInt1Ty(ctx), false);
std::vector<llvm::Type*> ArgTys;
ArgTys.push_back(llvm::Type::getInt8PtrTy(ctx));
llvm::FunctionType* FTy
= llvm::FunctionType::get(llvm::Type::getInt1Ty(ctx), ArgTys, false);
llvm::Function *CallBackFn
= llvm::cast<llvm::Function>(Md->getOrInsertFunction("shouldProceed", FTy));
llvm::Function* CallBackFn
= cast<llvm::Function>(Md->getOrInsertFunction("shouldProceed", FTy));
void* SemaRef = (void*)m_Sema;
// copied from JIT.cpp
llvm::Constant* SemaRefCnt = 0;
llvm::Type* constantIntTy = 0;
if (sizeof(void *) == 4)
constantIntTy = llvm::Type::getInt32Ty(ctx);
else
constantIntTy = llvm::Type::getInt64Ty(ctx);
SemaRefCnt = llvm::ConstantInt::get(constantIntTy, (uintptr_t)SemaRef);
llvm::Value *Arg = llvm::ConstantExpr::getIntToPtr(SemaRefCnt,
llvm::Type::getInt8PtrTy(ctx));
llvm::CallInst *CI = Builder->CreateCall(CallBackFn, Arg);
llvm::CallInst *CI = Builder->CreateCall(CallBackFn);
llvm::Value *TrueVl = llvm::ConstantInt::get(ctx, llvm::APInt(1, 1));
llvm::Value *RetVl = CI;
llvm::ICmpInst *Cmp
= new llvm::ICmpInst(*FailBB, llvm::CmpInst::ICMP_EQ, RetVl,
TrueVl, "");
@ -122,7 +142,7 @@ namespace cling {
return;
llvm::PointerType* PTy = llvm::cast<llvm::PointerType>(Addr->getType());
llvm::Type * ElTy = PTy -> getElementType();
llvm::Type * ElTy = PTy->getElementType();
if (!ElTy->isPointerTy()) {
llvm::BasicBlock *OldBB = LI->getParent();
llvm::ICmpInst *Cmp
@ -161,7 +181,7 @@ namespace cling {
bool NullDerefProtectionTransformer::runOnFunction(llvm::Function &F) {
llvm::IRBuilder<> TheBuilder(F.getContext());
Builder = &TheBuilder;
std::vector<llvm::Instruction*> WorkList;
for (llvm::inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) {
llvm::Instruction *I = &*i;

View File

@ -21,6 +21,7 @@ namespace llvm {
class BasicBlock;
class Function;
class LoadInst;
class Sema;
class StoreInst;
}
@ -33,19 +34,17 @@ namespace cling {
llvm::IRBuilder<>* Builder;
llvm::Instruction* Inst;
llvm::OwningPtr<clang::MangleContext> m_MangleCtx;
llvm::BasicBlock* getTrapBB();
void instrumentLoadInst(llvm::LoadInst* LI);
void instrumentStoreInst(llvm::StoreInst* SI);
bool runOnFunction(llvm::Function& F);
public:
NullDerefProtectionTransformer();
NullDerefProtectionTransformer(clang::Sema* S);
virtual ~NullDerefProtectionTransformer();
virtual void Transform();
};
} // end namespace cling

View File

@ -1,7 +1,14 @@
// RUN: cat %s | %cling | FileCheck %s
// RUN: cat %s | %cling -Xclang -verify
//This file checks a pointer load operation for null prt dereference.
int *p;
int x;
x = *p; // CHECK: Warning: you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]
x = *p; // expected-warning {{you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]}}
n
class MyClass {
public:
int a;
};
MyClass *m = 0;
if (m->a) { printf("MyClass's a=%d", m->a);} // expected-warning {{you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]}}
n
.q

View File

@ -1,6 +1,6 @@
// RUN: cat %s | %cling | FileCheck %s
// RUN: cat %s | %cling -Xclang -verify
//This file checks a pointer store operation for null prt dereference.
//This file checks a pointer store operation for null ptr dereference.
int *p;
*p = 6; // CHECK: Warning: you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]
*p = 6;
n