1313#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_TAINT_H
1414#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_TAINT_H
1515
16+ #include " clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
1617#include " clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
18+ #include " clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
1719#include " clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
1820
1921namespace clang {
@@ -23,27 +25,48 @@ namespace taint {
2325// / The type of taint, which helps to differentiate between different types of
2426// / taint.
2527using TaintTagType = unsigned ;
28+ using TaintFlowType = int ;
2629
2730static constexpr TaintTagType TaintTagGeneric = 0 ;
31+ static constexpr TaintFlowType UninitializedFlow = -1 ;
32+
33+ // / Used to store the taint flow related information
34+ // / in the program state.
35+ struct TaintData {
36+ TaintTagType Type; // Type of the taintedness (e.g. sql escape checked)
37+ TaintFlowType Flow; // Unique identifier of the taint flow
38+ TaintData () : Type(TaintTagGeneric), Flow(UninitializedFlow){};
39+ TaintData (TaintFlowType f) : Type(TaintTagGeneric), Flow(f){};
40+ TaintData (TaintTagType t, TaintFlowType f) : Type(t), Flow(f){};
41+ bool operator ==(const TaintData &X) const { return Flow == X.Flow ; }
42+ int operator <(const TaintData &X) const { return Flow < X.Flow ; }
43+ void Profile (llvm::FoldingSetNodeID &ID) const { ID.AddInteger (Flow); }
44+ };
45+
46+ static inline raw_ostream &operator <<(llvm::raw_ostream &Out,
47+ const clang::ento::taint::TaintData t) {
48+ Out << " Type:" << t.Type << " Flow:" << t.Flow << " \n " ;
49+ return Out;
50+ }
2851
2952// / Create a new state in which the value of the statement is marked as tainted.
3053[[nodiscard]] ProgramStateRef addTaint (ProgramStateRef State, const Stmt *S,
3154 const LocationContext *LCtx,
32- TaintTagType Kind = TaintTagGeneric );
55+ TaintData Data = TaintData() );
3356
3457// / Create a new state in which the value is marked as tainted.
3558[[nodiscard]] ProgramStateRef addTaint (ProgramStateRef State, SVal V,
36- TaintTagType Kind = TaintTagGeneric );
59+ TaintData Data = TaintData() );
3760
3861// / Create a new state in which the symbol is marked as tainted.
3962[[nodiscard]] ProgramStateRef addTaint (ProgramStateRef State, SymbolRef Sym,
40- TaintTagType Kind = TaintTagGeneric );
63+ TaintData Data = TaintData() );
4164
4265// / Create a new state in which the pointer represented by the region
4366// / is marked as tainted.
4467[[nodiscard]] ProgramStateRef addTaint (ProgramStateRef State,
4568 const MemRegion *R,
46- TaintTagType Kind = TaintTagGeneric );
69+ TaintData Data = TaintData() );
4770
4871[[nodiscard]] ProgramStateRef removeTaint (ProgramStateRef State, SVal V);
4972
@@ -56,10 +79,38 @@ static constexpr TaintTagType TaintTagGeneric = 0;
5679// / This might be necessary when referring to regions that can not have an
5780// / individual symbol, e.g. if they are represented by the default binding of
5881// / a LazyCompoundVal.
59- [[nodiscard]] ProgramStateRef
60- addPartialTaint (ProgramStateRef State, SymbolRef ParentSym,
61- const SubRegion *SubRegion,
62- TaintTagType Kind = TaintTagGeneric);
82+ [[nodiscard]] ProgramStateRef addPartialTaint (ProgramStateRef State,
83+ SymbolRef ParentSym,
84+ const SubRegion *SubRegion,
85+ TaintData = TaintData());
86+
87+ std::optional<TaintData> getTaintData (ProgramStateRef State, const Stmt *S,
88+ const LocationContext *LCtx);
89+
90+ // / Get the taint data for a value if tainted in the given state.
91+ std::optional<TaintData> getTaintData (ProgramStateRef State, SVal V);
92+
93+ // / Get the taint data for symbol if tainted in the given state.
94+ std::optional<TaintData> getTaintData (ProgramStateRef State, SymbolRef Sym);
95+
96+ // / Get the Taint data for a pointer represented by the region
97+ // if tainted in the given state.
98+ std::optional<TaintData> getTaintData (ProgramStateRef State, const MemRegion *Reg);
99+
100+ // / Check if the region the expression evaluates to is the standard input,
101+ // / and thus, is tainted.
102+ bool isStdin (SVal Val, const ASTContext &ACtx);
103+
104+ // / Returns the TaintData for a pointed value (if tainted), otherwise
105+ // / the TaintData of the pointer itself.
106+ std::optional<TaintData> getTaintDataPointeeOrPointer (const CheckerContext &C,
107+ SVal Arg);
108+ std::optional<TaintData> getTaintDataPointeeOrPointer (const Expr *E,
109+ const ProgramStateRef &State,
110+ CheckerContext &C);
111+
112+ SVal getPointeeOf (const CheckerContext &C, Loc LValue);
113+ std::optional<SVal> getPointeeOf (const CheckerContext &C, SVal Arg);
63114
64115// / Check if the statement has a tainted value in the given state.
65116bool isTainted (ProgramStateRef State, const Stmt *S,
@@ -84,19 +135,19 @@ void printTaint(ProgramStateRef State, raw_ostream &Out, const char *nl = "\n",
84135
85136LLVM_DUMP_METHOD void dumpTaint (ProgramStateRef State);
86137
87- // / The bug visitor prints a diagnostic message at the location where a given
88- // / variable was tainted.
89- class TaintBugVisitor final : public BugReporterVisitor {
90- private:
91- const SVal V;
92-
138+ // / Always use TaintBugReport to give taint related warnings in any checker.
139+ // / The TaintData member carries the flow associated data of the tainted SVal
140+ class TaintBugReport : public clang ::ento::PathSensitiveBugReport {
93141public:
94- TaintBugVisitor (const SVal V) : V(V) {}
95- void Profile (llvm::FoldingSetNodeID &ID) const override { ID.Add (V); }
96-
97- PathDiagnosticPieceRef VisitNode (const ExplodedNode *N,
98- BugReporterContext &BRC,
99- PathSensitiveBugReport &BR) override ;
142+ TaintBugReport (const BugType &bt, StringRef desc,
143+ const ExplodedNode *errorNode, TaintData T)
144+ : clang::ento::PathSensitiveBugReport(bt, desc, errorNode,
145+ Kind::TaintPathSensitive),
146+ taint_data (T){};
147+ static bool classof (const BugReport *R) {
148+ return R->getKind () == Kind::TaintPathSensitive;
149+ }
150+ TaintData taint_data;
100151};
101152
102153} // namespace taint
0 commit comments