diff options
author | Anna Zaks <ganna@apple.com> | 2013-03-09 03:23:19 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2013-03-09 03:23:19 +0000 |
commit | 0415998dd77986630efe8f1aed633519cc41e1f3 (patch) | |
tree | 8d6dc33ccbeb6581c17673eda42fd027fc503db8 /lib | |
parent | 80412c4e28c8247ad9c8d30d04c94938f01b21fb (diff) |
[analyzer] Make Suppress IDC checker aware that it might not start from the same node it was registered at
The visitor used to assume that the value it’s tracking is null in the first node it examines. This is not true.
If we are registering the Suppress Inlined Defensive checks visitor while traversing in another visitor
(such as FindlastStoreVisitor). When we restart with the IDC visitor, the invariance of the visitor does
not hold since the symbol we are tracking no longer exists at that point.
I had to pass the ErrorNode when creating the IDC visitor, because, in some cases, node N is
neither the error node nor will be visible along the path (we had not finalized the path at that point
and are dealing with ExplodedGraph.)
We should revisit the other visitors which might not be aware that they might get nodes, which are
later in path than the trigger point.
This suppresses a number of inline defensive checks in JavaScriptCore.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176756 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 4b6dd09021..88e4ba5876 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -695,7 +695,7 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, SuppressInlineDefensiveChecksVisitor:: SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N) - : V(Value), IsSatisfied(false) { + : V(Value), IsSatisfied(false), StartN(N) { assert(N->getState()->isNull(V).isConstrainedTrue() && "The visitor only tracks the cases where V is constrained to 0"); @@ -704,6 +704,7 @@ SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N) void SuppressInlineDefensiveChecksVisitor::Profile(FoldingSetNodeID &ID) const { static int id = 0; ID.AddPointer(&id); + ID.AddPointer(StartN); ID.Add(V); } @@ -712,13 +713,28 @@ const char *SuppressInlineDefensiveChecksVisitor::getTag() { } PathDiagnosticPiece * -SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *N, - const ExplodedNode *PrevN, +SuppressInlineDefensiveChecksVisitor::getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + BugReport &BR) { + if (StartN == BR.getErrorNode()) + StartN = 0; + return 0; +} + +PathDiagnosticPiece * +SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ, + const ExplodedNode *Pred, BugReporterContext &BRC, BugReport &BR) { if (IsSatisfied) return 0; + // Start tracking after we see node StartN. + if (StartN == Succ) + StartN = 0; + if (StartN) + return 0; + AnalyzerOptions &Options = BRC.getBugReporter().getEngine().getAnalysisManager().options; if (!Options.shouldSuppressInlinedDefensiveChecks()) @@ -726,14 +742,13 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *N, // Check if in the previous state it was feasible for this value // to *not* be null. - if (PrevN->getState()->assume(V, true)) { + if (Pred->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. + assert(!Succ->getState()->assume(V, true)); - // Check if this is inline defensive checks. - const LocationContext *CurLC = N->getLocationContext(); + // Check if this is inlined defensive checks. + const LocationContext *CurLC =Succ->getLocationContext(); const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext(); if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC)) BR.markInvalid("Suppress IDC", CurLC); @@ -741,14 +756,17 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *N, return 0; } -bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, +bool bugreporter::trackNullOrUndefValue(const ExplodedNode *ErrorNode, + const Stmt *S, BugReport &report, bool IsArg) { - if (!S || !N) + if (!S || !ErrorNode) return false; if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) S = OVE->getSourceExpr(); + const ExplodedNode *N = ErrorNode; + const Expr *LValue = 0; if (const Expr *Ex = dyn_cast<Expr>(S)) { Ex = Ex->IgnoreParenCasts(); @@ -850,10 +868,10 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, report.addVisitor(ConstraintTracker); // Add visitor, which will suppress inline defensive checks. - if (N->getState()->isNull(V).isConstrainedTrue()) { + if (ErrorNode->getState()->isNull(V).isConstrainedTrue()) { BugReporterVisitor *IDCSuppressor = new SuppressInlineDefensiveChecksVisitor(V.castAs<DefinedSVal>(), - N); + ErrorNode); report.addVisitor(IDCSuppressor); } } |