Index: lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -101,6 +101,22 @@ bool generateReportIfTainted(const Expr *E, const char Msg[], CheckerContext &C) const; + /// The bug visitor prints a diagnostic message at the location where a given + /// variable was tainted. + class TaintBugVisitor + : public BugReporterVisitorImpl { + private: + const SVal S; + + public: + TaintBugVisitor(const SVal S) : S(S) {} + void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(S); } + + std::shared_ptr VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) override; + }; typedef SmallVector ArgVector; @@ -194,6 +210,28 @@ /// points to data, which should be tainted on return. REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned) +std::shared_ptr +GenericTaintChecker::TaintBugVisitor::VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) { + + // Find the ExplodedNode where the taint was first introduced + if (!N->getState()->isTainted(S) || PrevN->getState()->isTainted(S)) + return nullptr; + + const Stmt *S = PathDiagnosticLocation::getStmt(N); + if (!S) + return nullptr; + + const LocationContext *NCtx = N->getLocationContext(); + PathDiagnosticLocation L = + PathDiagnosticLocation::createBegin(S, BRC.getSourceManager(), NCtx); + if (!L.isValid() || !L.asLocation().isValid()) + return nullptr; + + return std::make_shared( + L, "Taint originated here"); +} + GenericTaintChecker::TaintPropagationRule GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule( const FunctionDecl *FDecl, @@ -635,8 +673,13 @@ // Check for taint. ProgramStateRef State = C.getState(); - if (!State->isTainted(getPointedToSymbol(C, E)) && - !State->isTainted(E, C.getLocationContext())) + const SymbolRef PointedToSym = getPointedToSymbol(C, E); + SVal TaintedSVal; + if (State->isTainted(PointedToSym)) + TaintedSVal = nonloc::SymbolVal(PointedToSym); + else if (State->isTainted(E, C.getLocationContext())) + TaintedSVal = State->getSVal(E, C.getLocationContext()); + else return false; // Generate diagnostic. @@ -644,6 +687,7 @@ initBugType(); auto report = llvm::make_unique(*BT, Msg, N); report->addRange(E->getSourceRange()); + report->addVisitor(llvm::make_unique(TaintedSVal)); C.emitReport(std::move(report)); return true; }