forked from OSchip/llvm-project
[analyzer] Guard against C++ member functions that look like system functions.
C++ method calls and C function calls both appear as CallExprs in the AST. This was causing crashes for an object that had a 'free' method. <rdar://problem/11822244> llvm-svn: 160029
This commit is contained in:
parent
e8cb2fc616
commit
6cd16c5152
|
@ -299,6 +299,9 @@ void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
|
|||
CheckerContext &C) const {
|
||||
ProgramStateRef State = 0;
|
||||
const FunctionDecl *FDecl = C.getCalleeDecl(CE);
|
||||
if (!FDecl || FDecl->getKind() != Decl::Function)
|
||||
return;
|
||||
|
||||
StringRef Name = C.getCalleeName(FDecl);
|
||||
if (Name.empty())
|
||||
return;
|
||||
|
@ -372,7 +375,11 @@ void GenericTaintChecker::addSourcesPost(const CallExpr *CE,
|
|||
CheckerContext &C) const {
|
||||
// Define the attack surface.
|
||||
// Set the evaluation function by switching on the callee name.
|
||||
StringRef Name = C.getCalleeName(CE);
|
||||
const FunctionDecl *FDecl = C.getCalleeDecl(CE);
|
||||
if (!FDecl || FDecl->getKind() != Decl::Function)
|
||||
return;
|
||||
|
||||
StringRef Name = C.getCalleeName(FDecl);
|
||||
if (Name.empty())
|
||||
return;
|
||||
FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
|
||||
|
@ -406,6 +413,9 @@ bool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{
|
|||
return true;
|
||||
|
||||
const FunctionDecl *FDecl = C.getCalleeDecl(CE);
|
||||
if (!FDecl || FDecl->getKind() != Decl::Function)
|
||||
return false;
|
||||
|
||||
StringRef Name = C.getCalleeName(FDecl);
|
||||
if (Name.empty())
|
||||
return false;
|
||||
|
|
|
@ -290,7 +290,11 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
|
|||
unsigned idx = InvalidIdx;
|
||||
ProgramStateRef State = C.getState();
|
||||
|
||||
StringRef funName = C.getCalleeName(CE);
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD || FD->getKind() != Decl::Function)
|
||||
return;
|
||||
|
||||
StringRef funName = C.getCalleeName(FD);
|
||||
if (funName.empty())
|
||||
return;
|
||||
|
||||
|
@ -446,7 +450,11 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
|
|||
void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
ProgramStateRef State = C.getState();
|
||||
StringRef funName = C.getCalleeName(CE);
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD || FD->getKind() != Decl::Function)
|
||||
return;
|
||||
|
||||
StringRef funName = C.getCalleeName(FD);
|
||||
|
||||
// If a value has been allocated, add it to the set for tracking.
|
||||
unsigned idx = getTrackedFunctionIndex(funName, true);
|
||||
|
|
|
@ -387,16 +387,15 @@ bool MallocChecker::isAllocationFunction(const FunctionDecl *FD,
|
|||
if (!FD)
|
||||
return false;
|
||||
|
||||
IdentifierInfo *FunI = FD->getIdentifier();
|
||||
if (!FunI)
|
||||
return false;
|
||||
if (FD->getKind() == Decl::Function) {
|
||||
IdentifierInfo *FunI = FD->getIdentifier();
|
||||
initIdentifierInfo(C);
|
||||
|
||||
initIdentifierInfo(C);
|
||||
|
||||
if (FunI == II_malloc || FunI == II_realloc ||
|
||||
FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc ||
|
||||
FunI == II_strdup || FunI == II_strndup)
|
||||
return true;
|
||||
if (FunI == II_malloc || FunI == II_realloc ||
|
||||
FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc ||
|
||||
FunI == II_strdup || FunI == II_strndup)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Filter.CMallocOptimistic && FD->hasAttrs())
|
||||
for (specific_attr_iterator<OwnershipAttr>
|
||||
|
@ -412,14 +411,13 @@ bool MallocChecker::isFreeFunction(const FunctionDecl *FD, ASTContext &C) const
|
|||
if (!FD)
|
||||
return false;
|
||||
|
||||
IdentifierInfo *FunI = FD->getIdentifier();
|
||||
if (!FunI)
|
||||
return false;
|
||||
if (FD->getKind() == Decl::Function) {
|
||||
IdentifierInfo *FunI = FD->getIdentifier();
|
||||
initIdentifierInfo(C);
|
||||
|
||||
initIdentifierInfo(C);
|
||||
|
||||
if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf)
|
||||
return true;
|
||||
if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Filter.CMallocOptimistic && FD->hasAttrs())
|
||||
for (specific_attr_iterator<OwnershipAttr>
|
||||
|
@ -437,29 +435,32 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
|
|||
if (!FD)
|
||||
return;
|
||||
|
||||
initIdentifierInfo(C.getASTContext());
|
||||
IdentifierInfo *FunI = FD->getIdentifier();
|
||||
if (!FunI)
|
||||
return;
|
||||
|
||||
ProgramStateRef State = C.getState();
|
||||
if (FunI == II_malloc || FunI == II_valloc) {
|
||||
if (CE->getNumArgs() < 1)
|
||||
return;
|
||||
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
|
||||
} else if (FunI == II_realloc) {
|
||||
State = ReallocMem(C, CE, false);
|
||||
} else if (FunI == II_reallocf) {
|
||||
State = ReallocMem(C, CE, true);
|
||||
} else if (FunI == II_calloc) {
|
||||
State = CallocMem(C, CE);
|
||||
} else if (FunI == II_free) {
|
||||
State = FreeMemAux(C, CE, C.getState(), 0, false);
|
||||
} else if (FunI == II_strdup) {
|
||||
State = MallocUpdateRefState(C, CE, State);
|
||||
} else if (FunI == II_strndup) {
|
||||
State = MallocUpdateRefState(C, CE, State);
|
||||
} else if (Filter.CMallocOptimistic) {
|
||||
|
||||
if (FD->getKind() == Decl::Function) {
|
||||
initIdentifierInfo(C.getASTContext());
|
||||
IdentifierInfo *FunI = FD->getIdentifier();
|
||||
|
||||
if (FunI == II_malloc || FunI == II_valloc) {
|
||||
if (CE->getNumArgs() < 1)
|
||||
return;
|
||||
State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
|
||||
} else if (FunI == II_realloc) {
|
||||
State = ReallocMem(C, CE, false);
|
||||
} else if (FunI == II_reallocf) {
|
||||
State = ReallocMem(C, CE, true);
|
||||
} else if (FunI == II_calloc) {
|
||||
State = CallocMem(C, CE);
|
||||
} else if (FunI == II_free) {
|
||||
State = FreeMemAux(C, CE, State, 0, false);
|
||||
} else if (FunI == II_strdup) {
|
||||
State = MallocUpdateRefState(C, CE, State);
|
||||
} else if (FunI == II_strndup) {
|
||||
State = MallocUpdateRefState(C, CE, State);
|
||||
}
|
||||
}
|
||||
|
||||
if (Filter.CMallocOptimistic) {
|
||||
// Check all the attributes, if there are any.
|
||||
// There can be multiple of these attributes.
|
||||
if (FD->hasAttrs())
|
||||
|
|
|
@ -116,7 +116,7 @@ namespace ento {
|
|||
|
||||
bool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD)
|
||||
if (!FD || FD->getKind() != Decl::Function)
|
||||
return false;
|
||||
|
||||
ASTContext &Ctx = C.getASTContext();
|
||||
|
|
|
@ -325,7 +325,11 @@ void UnixAPIChecker::CheckVallocZero(CheckerContext &C,
|
|||
|
||||
void UnixAPIChecker::checkPreStmt(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
StringRef FName = C.getCalleeName(CE);
|
||||
const FunctionDecl *FD = C.getCalleeDecl(CE);
|
||||
if (!FD || FD->getKind() != Decl::Function)
|
||||
return;
|
||||
|
||||
StringRef FName = C.getCalleeName(FD);
|
||||
if (FName.empty())
|
||||
return;
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix,osx,experimental.unix,experimental.security.taint -analyzer-store region -verify %s
|
||||
|
||||
class Evil {
|
||||
public:
|
||||
void system(int); // taint checker
|
||||
void malloc(void *); // taint checker, malloc checker
|
||||
void free(); // malloc checker, keychain checker
|
||||
void fopen(); // stream checker
|
||||
void feof(int, int); // stream checker
|
||||
void open(); // unix api checker
|
||||
};
|
||||
|
||||
void test(Evil &E) {
|
||||
// no warnings, no crashes
|
||||
E.system(0);
|
||||
E.malloc(0);
|
||||
E.free();
|
||||
E.fopen();
|
||||
E.feof(0,1);
|
||||
E.open();
|
||||
}
|
Loading…
Reference in New Issue