aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-05-03 23:50:28 +0000
committerAnna Zaks <ganna@apple.com>2012-05-03 23:50:28 +0000
commitaca0ac58d2ae80d764e3832456667d7322445e0c (patch)
tree1567017774e9dd2a48fc094f2eb507521458934a /lib/StaticAnalyzer/Core
parentd964d6380945e0505b623050fe6a3f428008fc2a (diff)
[analyzer] Allow pointers escape through calls containing callback args.
(Since we don't have a generic pointer escape callback, modify ExprEngineCallAndReturn as well as the malloc checker.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156134 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp8
-rw-r--r--lib/StaticAnalyzer/Core/ObjCMessage.cpp66
2 files changed, 73 insertions, 1 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 4d0da06427..963dc90cdf 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -323,12 +323,14 @@ static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs,
// allocators/deallocators upon container construction.
// - NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
// be deallocated by NSMapRemove.
+ // - Any call that has a callback as one of the arguments.
if (FName == "pthread_setspecific" ||
FName == "funopen" ||
FName.endswith("NoCopy") ||
(FName.startswith("NS") &&
(FName.find("Insert") != StringRef::npos)) ||
- Call.isCFCGAllowingEscape(FName))
+ Call.isCFCGAllowingEscape(FName) ||
+ Call.hasNonZeroCallbackArg())
return;
}
@@ -344,6 +346,10 @@ static void findPtrToConstParams(llvm::SmallSet<unsigned, 1> &PreserveArgs,
if (const ObjCMethodDecl *MDecl = dyn_cast<ObjCMethodDecl>(CallDecl)) {
assert(MDecl->param_size() <= Call.getNumArgs());
unsigned Idx = 0;
+
+ if (Call.hasNonZeroCallbackArg())
+ return;
+
for (clang::ObjCMethodDecl::param_const_iterator
I = MDecl->param_begin(), E = MDecl->param_end(); I != E; ++I, ++Idx) {
if (isPointerToConst(*I))
diff --git a/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/lib/StaticAnalyzer/Core/ObjCMessage.cpp
index 65cdcd9d99..dc24e818ff 100644
--- a/lib/StaticAnalyzer/Core/ObjCMessage.cpp
+++ b/lib/StaticAnalyzer/Core/ObjCMessage.cpp
@@ -88,3 +88,69 @@ const Decl *CallOrObjCMessage::getDecl() const {
return 0;
}
+bool CallOrObjCMessage::isCallbackArg(unsigned Idx, const Type *T) const {
+ // Should we dig into struct fields, arrays ect?
+ if (T->isBlockPointerType() || T->isFunctionPointerType())
+ if (!getArgSVal(Idx).isZeroConstant())
+ return true;
+ return false;
+}
+
+bool CallOrObjCMessage::hasNonZeroCallbackArg() const {
+ unsigned NumOfArgs = getNumArgs();
+
+ // Process ObjC message first.
+ if (!CallE) {
+ const ObjCMethodDecl *D = Msg.getMethodDecl();
+ unsigned Idx = 0;
+ for (ObjCMethodDecl::param_const_iterator I = D->param_begin(),
+ E = D->param_end(); I != E; ++I, ++Idx) {
+ if (NumOfArgs <= Idx)
+ break;
+
+ if (isCallbackArg(Idx, (*I)->getType().getTypePtr()))
+ return true;
+ }
+ return false;
+ }
+
+ // Else, assume we are dealing with a Function call.
+ const FunctionDecl *FD = 0;
+ if (const CXXConstructExpr *Ctor =
+ CallE.dyn_cast<const CXXConstructExpr *>())
+ FD = Ctor->getConstructor();
+
+ const CallExpr * CE = CallE.get<const CallExpr *>();
+ FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
+
+ // If calling using a function pointer, assume the function does not
+ // have a callback. TODO: We could check the types of the arguments here.
+ if (!FD)
+ return false;
+
+ unsigned Idx = 0;
+ for (FunctionDecl::param_const_iterator I = FD->param_begin(),
+ E = FD->param_end(); I != E; ++I, ++Idx) {
+ if (NumOfArgs <= Idx)
+ break;
+
+ if (isCallbackArg(Idx, (*I)->getType().getTypePtr()))
+ return true;
+ }
+ return false;
+}
+
+bool CallOrObjCMessage::isCFCGAllowingEscape(StringRef FName) {
+ if (FName[0] == 'C' && (FName[1] == 'F' || FName[1] == 'G'))
+ if (StrInStrNoCase(FName, "InsertValue") != StringRef::npos||
+ StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "WithData") != StringRef::npos ||
+ StrInStrNoCase(FName, "AppendValue") != StringRef::npos||
+ StrInStrNoCase(FName, "SetAttribute") != StringRef::npos) {
+ return true;
+ }
+ return false;
+}
+
+