aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp55
-rw-r--r--lib/StaticAnalyzer/Core/ProgramState.cpp10
2 files changed, 64 insertions, 1 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index bb20c0d3c6..b4ba2d4789 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -27,6 +27,8 @@
using namespace clang;
using namespace ento;
+using llvm::FoldingSetNodeID;
+
//===----------------------------------------------------------------------===//
// Utility functions.
//===----------------------------------------------------------------------===//
@@ -663,6 +665,49 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
return NULL;
}
+SuppressInlineDefensiveChecksVisitor::
+SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N)
+ : V(Value), IsSatisfied(false) {
+
+ assert(N->getState()->isNull(V).isConstrainedTrue() &&
+ "The visitor only tracks the cases where V is constrained to 0");
+}
+
+void SuppressInlineDefensiveChecksVisitor::Profile(FoldingSetNodeID &ID) const {
+ static int id = 0;
+ ID.AddPointer(&id);
+ ID.Add(V);
+}
+
+const char *SuppressInlineDefensiveChecksVisitor::getTag() {
+ return "IDCVisitor";
+}
+
+PathDiagnosticPiece *
+SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) {
+ if (IsSatisfied)
+ return 0;
+
+ // Check if in the previous state it was feasible for this value
+ // to *not* be null.
+ if (PrevN->getState()->assume(V, true)) {
+ IsSatisfied = true;
+
+ // TODO: Investigate if missing the transition point, where V
+ // is non-null in N could lead to false negatives.
+
+ // Check if this is inline defensive checks.
+ const LocationContext *CurLC = PrevN->getLocationContext();
+ const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
+ if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC))
+ BR.markInvalid("Suppress IDC", CurLC);
+ }
+ return 0;
+}
+
bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S,
BugReport &report, bool IsArg) {
if (!S || !N)
@@ -772,8 +817,16 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S,
// If the contents are symbolic, find out when they became null.
if (V.getAsLocSymbol()) {
BugReporterVisitor *ConstraintTracker =
- new TrackConstraintBRVisitor(V.castAs<DefinedSVal>(), false);
+ new TrackConstraintBRVisitor(V.castAs<DefinedSVal>(), false);
report.addVisitor(ConstraintTracker);
+
+ // Add visitor, which will suppress inline defensive checks.
+ if (N->getState()->isNull(V).isConstrainedTrue()) {
+ BugReporterVisitor *IDCSuppressor =
+ new SuppressInlineDefensiveChecksVisitor(V.castAs<DefinedSVal>(),
+ N);
+ report.addVisitor(IDCSuppressor);
+ }
}
if (Optional<KnownSVal> KV = V.getAs<KnownSVal>())
diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp
index 400569e49a..64205f8d99 100644
--- a/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -324,6 +324,16 @@ ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
return CM.assume(this, inBound.castAs<DefinedSVal>(), Assumption);
}
+ConditionTruthVal ProgramState::isNull(SVal V) const {
+ if (V.isZeroConstant())
+ return true;
+
+ SymbolRef Sym = V.getAsSymbol();
+ if (!Sym)
+ return false;
+ return getStateManager().ConstraintMgr->isNull(this, Sym);
+}
+
ProgramStateRef ProgramStateManager::getInitialState(const LocationContext *InitLoc) {
ProgramState State(this,
EnvMgr.getInitialEnvironment(),