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<TaintBugVisitor> {
+ private:
+ const SVal V;
+
+ public:
+ TaintBugVisitor(const SVal V) : V(V) {}
+ void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(V); }
+
+ std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR) override;
+ };
typedef SmallVector<unsigned, 2> ArgVector;
/// points to data, which should be tainted on return.
REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned)
+std::shared_ptr<PathDiagnosticPiece>
+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(V) || PrevN->getState()->isTainted(V))
+ 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<PathDiagnosticEventPiece>(
+ L, "Taint originated here");
+}
+
GenericTaintChecker::TaintPropagationRule
GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
const FunctionDecl *FDecl,
// 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 = C.getSVal(E);
+ else
return false;
// Generate diagnostic.
initBugType();
auto report = llvm::make_unique<BugReport>(*BT, Msg, N);
report->addRange(E->getSourceRange());
+ report->addVisitor(llvm::make_unique<TaintBugVisitor>(TaintedSVal));
C.emitReport(std::move(report));
return true;
}