summaryrefslogtreecommitdiffstats
path: root/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-02-04 06:40:52 +0000
committerAnna Zaks <ganna@apple.com>2012-02-04 06:40:52 +0000
commite59ec3dfe17c1ceb648861b621a3890a9a56ab0c (patch)
treef16090435c52cb41b7219aaa770f642ec39bb2c4 /lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
parenta506586ad3cb0f3635b0e77b86e5e9e5fb2ccc17 (diff)
[analyzer] Make sure Containers OutOfBounds checker does not crash on undefined arguments, when CF functions are called with wrong number of arguments.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149771 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp34
1 files changed, 14 insertions, 20 deletions
diff --git a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
index 2a677bc3dd..0b16b87be3 100644
--- a/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
@@ -56,18 +56,8 @@ public:
};
} // end anonymous namespace
-// Array state stores the array size on creation (allocation).
-// Size might be an unsigned or a symbol.
-struct ArraySize {
- SVal NLSize;
- ArraySize(SVal s) : NLSize(s) {}
- void Profile(llvm::FoldingSetNodeID &ID) const {
- NLSize.Profile(ID);
- }
-};
-
// ProgramState trait - a map from array symbol to it's state.
-typedef llvm::ImmutableMap<SymbolRef, SVal> ArraySizeM;
+typedef llvm::ImmutableMap<SymbolRef, DefinedSVal> ArraySizeM;
namespace { struct ArraySizeMap {}; }
namespace clang { namespace ento {
@@ -91,18 +81,20 @@ void ObjCContainersChecker::addSizeInfo(const Expr *Array, const Expr *Size,
if (!ArraySym)
return;
- C.addTransition(State->set<ArraySizeMap>(ArraySym, SizeV));
+ C.addTransition(State->set<ArraySizeMap>(ArraySym, cast<DefinedSVal>(SizeV)));
return;
}
void ObjCContainersChecker::checkPostStmt(const CallExpr *CE,
CheckerContext &C) const {
StringRef Name = C.getCalleeName(CE);
- if (Name.empty())
+ if (Name.empty() || CE->getNumArgs() < 1)
return;
// Add array size information to the state.
if (Name.equals("CFArrayCreate")) {
+ if (CE->getNumArgs() < 3)
+ return;
// Note, we can visit the Create method in the post-visit because
// the CFIndex parameter is passed in by value and will not be invalidated
// by the call.
@@ -119,7 +111,7 @@ void ObjCContainersChecker::checkPostStmt(const CallExpr *CE,
void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
CheckerContext &C) const {
StringRef Name = C.getCalleeName(CE);
- if (Name.empty())
+ if (Name.empty() || CE->getNumArgs() < 2)
return;
// Check the array access.
@@ -128,20 +120,22 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
// Retrieve the size.
// Find out if we saw this array symbol before and have information about it.
const Expr *ArrayExpr = CE->getArg(0);
- const SVal *SizeVal = State->get<ArraySizeMap>(getArraySym(ArrayExpr, C));
- if (!SizeVal)
+ const DefinedSVal *Size =
+ State->get<ArraySizeMap>(getArraySym(ArrayExpr, C));
+ if (!Size)
return;
- DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(*SizeVal);
// Get the index.
const Expr *IdxExpr = CE->getArg(1);
SVal IdxVal = State->getSVal(IdxExpr, C.getLocationContext());
- DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(IdxVal);
+ if (IdxVal.isUnknownOrUndef())
+ return;
+ DefinedSVal Idx = cast<DefinedSVal>(IdxVal);
// Now, check if 'Idx in [0, Size-1]'.
const QualType T = IdxExpr->getType();
- ProgramStateRef StInBound = State->assumeInBound(Idx, Size, true, T);
- ProgramStateRef StOutBound = State->assumeInBound(Idx, Size, false, T);
+ ProgramStateRef StInBound = State->assumeInBound(Idx, *Size, true, T);
+ ProgramStateRef StOutBound = State->assumeInBound(Idx, *Size, false, T);
if (StOutBound && !StInBound) {
ExplodedNode *N = C.generateSink(StOutBound);
if (!N)