aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-03-09 01:13:14 +0000
committerTed Kremenek <kremenek@apple.com>2012-03-09 01:13:14 +0000
commit76aadc346c3a4c363238a1e1232f324c3355d9e0 (patch)
tree7971c167492a0aa90e5961bb9e6db4f8eef5c110 /lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
parentd95e0b830ed031f2ea0e15e3679cd51b9bf23a9c (diff)
[analyzer] Implement basic path diagnostic pruning based on "interesting" symbols and regions.
Essentially, a bug centers around a story for various symbols and regions. We should only include the path diagnostic events that relate to those symbols and regions. The pruning is done by associating a set of interesting symbols and regions with a BugReporter, which can be modified at BugReport creation or by BugReporterVisitors. This patch reduces the diagnostics emitted in several of our test cases. I've vetted these as having desired behavior. The only regression is a missing null check diagnostic for the return value of realloc() in test/Analysis/malloc-plist.c. This will require some investigation to fix, and I have added a FIXME to the test case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152361 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp48
1 files changed, 35 insertions, 13 deletions
diff --git a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
index 7e4761cdf8..81a27451cb 100644
--- a/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -34,28 +34,35 @@ public:
void checkLocation(SVal location, bool isLoad, const Stmt* S,
CheckerContext &C) const;
- static void AddDerefSource(raw_ostream &os,
+ static const MemRegion *AddDerefSource(raw_ostream &os,
SmallVectorImpl<SourceRange> &Ranges,
- const Expr *Ex, bool loadedFrom = false);
+ const Expr *Ex, const ProgramState *state,
+ const LocationContext *LCtx,
+ bool loadedFrom = false);
};
} // end anonymous namespace
-void DereferenceChecker::AddDerefSource(raw_ostream &os,
- SmallVectorImpl<SourceRange> &Ranges,
- const Expr *Ex,
- bool loadedFrom) {
+const MemRegion *
+DereferenceChecker::AddDerefSource(raw_ostream &os,
+ SmallVectorImpl<SourceRange> &Ranges,
+ const Expr *Ex,
+ const ProgramState *state,
+ const LocationContext *LCtx,
+ bool loadedFrom) {
Ex = Ex->IgnoreParenLValueCasts();
+ const MemRegion *sourceR = 0;
switch (Ex->getStmtClass()) {
default:
- return;
+ break;
case Stmt::DeclRefExprClass: {
const DeclRefExpr *DR = cast<DeclRefExpr>(Ex);
if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
os << " (" << (loadedFrom ? "loaded from" : "from")
<< " variable '" << VD->getName() << "')";
Ranges.push_back(DR->getSourceRange());
+ sourceR = state->getLValue(VD, LCtx).getAsRegion();
}
- return;
+ break;
}
case Stmt::MemberExprClass: {
const MemberExpr *ME = cast<MemberExpr>(Ex);
@@ -66,6 +73,7 @@ void DereferenceChecker::AddDerefSource(raw_ostream &os,
break;
}
}
+ return sourceR;
}
void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
@@ -79,7 +87,7 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
BugReport *report =
new BugReport(*BT_undef, BT_undef->getDescription(), N);
report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
- bugreporter::GetDerefExpr(N)));
+ bugreporter::GetDerefExpr(N), report));
C.EmitReport(report);
}
return;
@@ -92,6 +100,7 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
return;
ProgramStateRef state = C.getState();
+ const LocationContext *LCtx = C.getLocationContext();
ProgramStateRef notNullState, nullState;
llvm::tie(notNullState, nullState) = state->assume(location);
@@ -115,13 +124,17 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
// that syntactically caused the load.
if (const Expr *expr = dyn_cast<Expr>(S))
S = expr->IgnoreParenLValueCasts();
+
+ const MemRegion *sourceR = 0;
switch (S->getStmtClass()) {
case Stmt::ArraySubscriptExprClass: {
llvm::raw_svector_ostream os(buf);
os << "Array access";
const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(S);
- AddDerefSource(os, Ranges, AE->getBase()->IgnoreParenCasts());
+ sourceR =
+ AddDerefSource(os, Ranges, AE->getBase()->IgnoreParenCasts(),
+ state.getPtr(), LCtx);
os << " results in a null pointer dereference";
break;
}
@@ -129,7 +142,9 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
llvm::raw_svector_ostream os(buf);
os << "Dereference of null pointer";
const UnaryOperator *U = cast<UnaryOperator>(S);
- AddDerefSource(os, Ranges, U->getSubExpr()->IgnoreParens(), true);
+ sourceR =
+ AddDerefSource(os, Ranges, U->getSubExpr()->IgnoreParens(),
+ state.getPtr(), LCtx, true);
break;
}
case Stmt::MemberExprClass: {
@@ -138,7 +153,9 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
llvm::raw_svector_ostream os(buf);
os << "Access to field '" << M->getMemberNameInfo()
<< "' results in a dereference of a null pointer";
- AddDerefSource(os, Ranges, M->getBase()->IgnoreParenCasts(), true);
+ sourceR =
+ AddDerefSource(os, Ranges, M->getBase()->IgnoreParenCasts(),
+ state.getPtr(), LCtx, true);
}
break;
}
@@ -165,12 +182,17 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
N);
report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N,
- bugreporter::GetDerefExpr(N)));
+ bugreporter::GetDerefExpr(N), report));
for (SmallVectorImpl<SourceRange>::iterator
I = Ranges.begin(), E = Ranges.end(); I!=E; ++I)
report->addRange(*I);
+ if (sourceR) {
+ report->markInteresting(sourceR);
+ report->markInteresting(state->getRawSVal(loc::MemRegionVal(sourceR)));
+ }
+
C.EmitReport(report);
return;
}