mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-02 23:50:19 +00:00
[analyzer] Refactor checkers to use helper function for getting callee Decl and name.
We are getting name of the called function or it's declaration in a few checkers. Refactor them to use the helper function in the CheckerContext. llvm-svn: 145576
This commit is contained in:
parent
24fc93a940
commit
c6aa531a8f
@ -142,6 +142,9 @@ public:
|
||||
Eng.getBugReporter().EmitReport(R);
|
||||
}
|
||||
|
||||
/// \brief Get the declaration of the called function (path-sensitive).
|
||||
const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
|
||||
|
||||
/// \brief Get the name of the called function (path-sensitive).
|
||||
StringRef getCalleeName(const CallExpr *CE) const;
|
||||
|
||||
|
@ -249,11 +249,8 @@ static const char* GetCFNumberTypeStr(uint64_t i) {
|
||||
|
||||
void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const Expr *Callee = CE->getCallee();
|
||||
const ProgramState *state = C.getState();
|
||||
SVal CallV = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = CallV.getAsFunctionDecl();
|
||||
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD)
|
||||
return;
|
||||
|
||||
@ -363,11 +360,8 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
|
||||
if (CE->getNumArgs() != 1)
|
||||
return;
|
||||
|
||||
// Get the function declaration of the callee.
|
||||
const ProgramState *state = C.getState();
|
||||
SVal X = state->getSVal(CE->getCallee());
|
||||
const FunctionDecl *FD = X.getAsFunctionDecl();
|
||||
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD)
|
||||
return;
|
||||
|
||||
|
@ -30,12 +30,9 @@ public:
|
||||
}
|
||||
|
||||
bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
|
||||
CheckerContext &C) const{
|
||||
CheckerContext &C) const {
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD)
|
||||
return false;
|
||||
|
||||
|
@ -1664,20 +1664,9 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
// Get the callee. All the functions we care about are C functions
|
||||
// with simple identifiers.
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
|
||||
|
||||
if (!FD)
|
||||
StringRef Name = C.getCalleeName(CE);
|
||||
if (Name.empty())
|
||||
return false;
|
||||
|
||||
// Get the name of the callee. If it's a builtin, strip off the prefix.
|
||||
IdentifierInfo *II = FD->getIdentifier();
|
||||
if (!II) // if no identifier, not a simple C function
|
||||
return false;
|
||||
StringRef Name = II->getName();
|
||||
if (Name.startswith("__builtin_"))
|
||||
Name = Name.substr(10);
|
||||
|
||||
|
@ -62,10 +62,7 @@ private:
|
||||
} // end anonymous namespace
|
||||
|
||||
bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD)
|
||||
return false;
|
||||
|
||||
@ -125,10 +122,7 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
|
||||
|
||||
// Check the jail state before any function call except chroot and chdir().
|
||||
void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD)
|
||||
return;
|
||||
|
||||
@ -143,7 +137,7 @@ void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
|
||||
return;
|
||||
|
||||
// If jail state is ROOT_CHANGED, generate BugReport.
|
||||
void *const* k = state->FindGDM(ChrootChecker::getTag());
|
||||
void *const* k = C.getState()->FindGDM(ChrootChecker::getTag());
|
||||
if (k)
|
||||
if (isRootChanged((intptr_t) *k))
|
||||
if (ExplodedNode *N = C.addTransition()) {
|
||||
|
@ -281,18 +281,12 @@ void MacOSKeychainAPIChecker::
|
||||
|
||||
void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const ProgramState *State = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = State->getSVal(Callee);
|
||||
unsigned idx = InvalidIdx;
|
||||
const ProgramState *State = C.getState();
|
||||
|
||||
const FunctionDecl *funDecl = L.getAsFunctionDecl();
|
||||
if (!funDecl)
|
||||
StringRef funName = C.getCalleeName(CE);
|
||||
if (funName.empty())
|
||||
return;
|
||||
IdentifierInfo *funI = funDecl->getIdentifier();
|
||||
if (!funI)
|
||||
return;
|
||||
StringRef funName = funI->getName();
|
||||
|
||||
// If it is a call to an allocator function, it could be a double allocation.
|
||||
idx = getTrackedFunctionIndex(funName, true);
|
||||
|
@ -37,11 +37,11 @@ public:
|
||||
void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
|
||||
|
||||
void CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
|
||||
const IdentifierInfo *FI) const;
|
||||
StringRef FName) const;
|
||||
|
||||
typedef void (MacOSXAPIChecker::*SubChecker)(CheckerContext &,
|
||||
const CallExpr *,
|
||||
const IdentifierInfo *) const;
|
||||
StringRef FName) const;
|
||||
};
|
||||
} //end anonymous namespace
|
||||
|
||||
@ -50,7 +50,7 @@ public:
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
|
||||
const IdentifierInfo *FI) const {
|
||||
StringRef FName) const {
|
||||
if (CE->getNumArgs() < 1)
|
||||
return;
|
||||
|
||||
@ -71,7 +71,7 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
|
||||
|
||||
llvm::SmallString<256> S;
|
||||
llvm::raw_svector_ostream os(S);
|
||||
os << "Call to '" << FI->getName() << "' uses";
|
||||
os << "Call to '" << FName << "' uses";
|
||||
if (const VarRegion *VR = dyn_cast<VarRegion>(R))
|
||||
os << " the local variable '" << VR->getDecl()->getName() << '\'';
|
||||
else
|
||||
@ -92,27 +92,18 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
|
||||
|
||||
void MacOSXAPIChecker::checkPreStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
// FIXME: This sort of logic is common to several checkers, including
|
||||
// UnixAPIChecker, PthreadLockChecker, and CStringChecker. Should refactor.
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
const FunctionDecl *Fn = state->getSVal(Callee).getAsFunctionDecl();
|
||||
|
||||
if (!Fn)
|
||||
return;
|
||||
|
||||
const IdentifierInfo *FI = Fn->getIdentifier();
|
||||
if (!FI)
|
||||
StringRef Name = C.getCalleeName(CE);
|
||||
if (Name.empty())
|
||||
return;
|
||||
|
||||
SubChecker SC =
|
||||
llvm::StringSwitch<SubChecker>(FI->getName())
|
||||
llvm::StringSwitch<SubChecker>(Name)
|
||||
.Cases("dispatch_once", "dispatch_once_f",
|
||||
&MacOSXAPIChecker::CheckDispatchOnce)
|
||||
.Default(NULL);
|
||||
|
||||
if (SC)
|
||||
(this->*SC)(C, CE, FI);
|
||||
(this->*SC)(C, CE, Name);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -128,11 +128,7 @@ namespace ento {
|
||||
}
|
||||
|
||||
bool MallocChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD)
|
||||
return false;
|
||||
|
||||
|
@ -35,24 +35,27 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
static StringRef getCalleeName(const ProgramState *State,
|
||||
const CallExpr *CE) {
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = State->getSVal(Callee);
|
||||
const FunctionDecl *funDecl = L.getAsFunctionDecl();
|
||||
if (!funDecl)
|
||||
return StringRef();
|
||||
IdentifierInfo *funI = funDecl->getIdentifier();
|
||||
if (!funI)
|
||||
return StringRef();
|
||||
return funI->getName();
|
||||
}
|
||||
|
||||
bool OSAtomicChecker::inlineCall(const CallExpr *CE,
|
||||
ExprEngine &Eng,
|
||||
ExplodedNode *Pred,
|
||||
ExplodedNodeSet &Dst) const {
|
||||
const ProgramState *state = Pred->getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
if (!FD)
|
||||
StringRef FName = getCalleeName(Pred->getState(), CE);
|
||||
if (FName.empty())
|
||||
return false;
|
||||
|
||||
const IdentifierInfo *II = FD->getIdentifier();
|
||||
if (!II)
|
||||
return false;
|
||||
|
||||
StringRef FName(II->getName());
|
||||
|
||||
// Check for compare and swap.
|
||||
if (FName.startswith("OSAtomicCompareAndSwap") ||
|
||||
FName.startswith("objc_atomicCompareAndSwap"))
|
||||
|
@ -57,18 +57,10 @@ template <> struct ProgramStateTrait<LockSet> :
|
||||
void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
|
||||
|
||||
if (!FD)
|
||||
StringRef FName = C.getCalleeName(CE);
|
||||
if (FName.empty())
|
||||
return;
|
||||
|
||||
// Get the name of the callee.
|
||||
IdentifierInfo *II = FD->getIdentifier();
|
||||
if (!II) // if no identifier, not a simple C function
|
||||
return;
|
||||
StringRef FName = II->getName();
|
||||
|
||||
if (CE->getNumArgs() != 1)
|
||||
return;
|
||||
|
||||
|
@ -2990,10 +2990,7 @@ void RetainCountChecker::processNonLeakError(const ProgramState *St,
|
||||
bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
// Get the callee. We're only interested in simple C functions.
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD)
|
||||
return false;
|
||||
|
||||
@ -3015,7 +3012,7 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
// See if it's one of the specific functions we know how to eval.
|
||||
bool canEval = false;
|
||||
|
||||
QualType ResultTy = FD->getResultType();
|
||||
QualType ResultTy = CE->getCallReturnType();
|
||||
if (ResultTy->isObjCIdType()) {
|
||||
// Handle: id NSMakeCollectable(CFTypeRef)
|
||||
canEval = II->isStr("NSMakeCollectable");
|
||||
|
@ -115,10 +115,7 @@ namespace ento {
|
||||
}
|
||||
|
||||
bool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = state->getSVal(Callee);
|
||||
const FunctionDecl *FD = L.getAsFunctionDecl();
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD)
|
||||
return false;
|
||||
|
||||
|
@ -224,21 +224,12 @@ void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void UnixAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
|
||||
// Get the callee. All the functions we care about are C functions
|
||||
// with simple identifiers.
|
||||
const ProgramState *state = C.getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
const FunctionDecl *Fn = state->getSVal(Callee).getAsFunctionDecl();
|
||||
|
||||
if (!Fn)
|
||||
return;
|
||||
|
||||
const IdentifierInfo *FI = Fn->getIdentifier();
|
||||
if (!FI)
|
||||
StringRef FName = C.getCalleeName(CE);
|
||||
if (FName.empty())
|
||||
return;
|
||||
|
||||
SubChecker SC =
|
||||
llvm::StringSwitch<SubChecker>(FI->getName())
|
||||
llvm::StringSwitch<SubChecker>(FName)
|
||||
.Case("open", &UnixAPIChecker::CheckOpen)
|
||||
.Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
|
||||
.Case("malloc", &UnixAPIChecker::CheckMallocZero)
|
||||
|
@ -16,12 +16,15 @@
|
||||
using namespace clang;
|
||||
using namespace ento;
|
||||
|
||||
StringRef CheckerContext::getCalleeName(const CallExpr *CE) const {
|
||||
const FunctionDecl *CheckerContext::getCalleeDecl(const CallExpr *CE) const {
|
||||
const ProgramState *State = getState();
|
||||
const Expr *Callee = CE->getCallee();
|
||||
SVal L = State->getSVal(Callee);
|
||||
return L.getAsFunctionDecl();
|
||||
}
|
||||
|
||||
const FunctionDecl *funDecl = L.getAsFunctionDecl();
|
||||
StringRef CheckerContext::getCalleeName(const CallExpr *CE) const {
|
||||
const FunctionDecl *funDecl = getCalleeDecl(CE);
|
||||
if (!funDecl)
|
||||
return StringRef();
|
||||
IdentifierInfo *funI = funDecl->getIdentifier();
|
||||
|
Loading…
x
Reference in New Issue
Block a user