diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 73 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 4 |
2 files changed, 50 insertions, 27 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 213a52a9b9..dace7f3c8b 100644 --- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -283,6 +283,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, const ExplodedNode *StoreSite = 0; const Expr *InitE = 0; + bool IsParam = false; // First see if we reached the declaration of the region. if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { @@ -327,6 +328,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(), Succ->getState()); InitE = Call->getArgExpr(Param->getFunctionScopeIndex()); + IsParam = true; } } @@ -337,12 +339,14 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, // If we have an expression that provided the value, try to track where it // came from. if (InitE) { - InitE = InitE->IgnoreParenCasts(); - - if (V.isUndef() || isa<loc::ConcreteInt>(V)) - bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR); - else - ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE, BR); + if (V.isUndef() || isa<loc::ConcreteInt>(V)) { + if (!IsParam) + InitE = InitE->IgnoreParenCasts(); + bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam); + } else { + ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(), + BR); + } } if (!R->canPrintPretty()) @@ -522,30 +526,32 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, } void bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, - BugReport &report) { + BugReport &report, bool IsArg) { if (!S || !N) return; if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) S = OVE->getSourceExpr(); - ProgramStateManager &StateMgr = N->getState()->getStateManager(); - - // Walk through nodes until we get one that matches the statement exactly. - while (N) { - const ProgramPoint &pp = N->getLocation(); - if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) { - if (ps->getStmt() == S) - break; - } else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&pp)) { - if (CEE->getCalleeContext()->getCallSite() == S) - break; - } - N = N->getFirstPred(); - } + if (IsArg) { + assert(isa<CallEnter>(N->getLocation()) && "Tracking arg but not at call"); + } else { + // Walk through nodes until we get one that matches the statement exactly. + do { + const ProgramPoint &pp = N->getLocation(); + if (const PostStmt *ps = dyn_cast<PostStmt>(&pp)) { + if (ps->getStmt() == S) + break; + } else if (const CallExitEnd *CEE = dyn_cast<CallExitEnd>(&pp)) { + if (CEE->getCalleeContext()->getCallSite() == S) + break; + } + N = N->getFirstPred(); + } while (N); - if (!N) - return; + if (!N) + return; + } ProgramStateRef state = N->getState(); @@ -560,11 +566,28 @@ void bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, // FIXME: Right now we only track VarDecls because it's non-trivial to // get a MemRegion for any other DeclRefExprs. <rdar://problem/12114812> if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { - const VarRegion *R = - StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); + ProgramStateManager &StateMgr = state->getStateManager(); + MemRegionManager &MRMgr = StateMgr.getRegionManager(); + const VarRegion *R = MRMgr.getVarRegion(VD, N->getLocationContext()); // Mark both the variable region and its contents as interesting. SVal V = state->getRawSVal(loc::MemRegionVal(R)); + + // If the value matches the default for the variable region, that + // might mean that it's been cleared out of the state. Fall back to + // the full argument expression (with casts and such intact). + if (IsArg) { + bool UseArgValue = V.isUnknownOrUndef() || V.isZeroConstant(); + if (!UseArgValue) { + const SymbolRegionValue *SRV = + dyn_cast_or_null<SymbolRegionValue>(V.getAsLocSymbol()); + if (SRV) + UseArgValue = (SRV->getRegion() == R); + } + if (UseArgValue) + V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); + } + report.markInteresting(R); report.markInteresting(V); report.addVisitor(new UndefOrNullArgVisitor(R)); diff --git a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp index 9b70d6861c..c284bd7dfa 100644 --- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp +++ b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp @@ -61,7 +61,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) { // // (1) 1 predecessor (that has one successor) // (2) 1 successor (that has one predecessor) - // (3) The ProgramPoint is for a PostStmt. + // (3) The ProgramPoint is for a PostStmt, but not a PostStore. // (4) There is no 'tag' for the ProgramPoint. // (5) The 'store' is the same as the predecessor. // (6) The 'GDM' is the same as the predecessor. @@ -85,7 +85,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) { // Condition 3. ProgramPoint progPoint = node->getLocation(); - if (!isa<PostStmt>(progPoint)) + if (!isa<PostStmt>(progPoint) || isa<PostStore>(progPoint)) return false; // Condition 4. |