blob: 32fed202d3ab648eb9b5c91b971e1824ea336bae [file] [log] [blame]
Anna Zaks5c5bf9b2011-11-16 19:58:13 +00001//== GenericTaintChecker.cpp ----------------------------------- -*- C++ -*--=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This checker defines the attack surface for generic taint propagation.
11//
12// The taint information produced by it might be useful to other checkers. For
13// example, checkers should report errors which involve tainted data more
14// aggressively, even if the involved symbols are under constrained.
15//
16//===----------------------------------------------------------------------===//
Kristof Umann76a21502018-12-15 16:23:51 +000017#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000018#include "clang/AST/Attr.h"
19#include "clang/Basic/Builtins.h"
20#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
Anna Zaks5c5bf9b2011-11-16 19:58:13 +000021#include "clang/StaticAnalyzer/Core/Checker.h"
22#include "clang/StaticAnalyzer/Core/CheckerManager.h"
23#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
Anna Zaks3b0ab202011-12-17 00:26:34 +000024#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
Anna Zaksb3fa8d72012-01-12 02:22:34 +000025#include <climits>
Anna Zaks5c5bf9b2011-11-16 19:58:13 +000026
27using namespace clang;
28using namespace ento;
29
30namespace {
Artem Dergachevb68cb542018-12-19 23:35:08 +000031class GenericTaintChecker
32 : public Checker<check::PostStmt<CallExpr>, check::PreStmt<CallExpr>> {
Anna Zaks3b0ab202011-12-17 00:26:34 +000033public:
Artem Dergachevb68cb542018-12-19 23:35:08 +000034 static void *getTag() {
35 static int Tag;
36 return &Tag;
37 }
Anna Zaks0244cd72012-01-14 02:48:40 +000038
39 void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks0244cd72012-01-14 02:48:40 +000040
41 void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks5c5bf9b2011-11-16 19:58:13 +000042
Anna Zaks3b0ab202011-12-17 00:26:34 +000043private:
Anna Zaksbf740512012-01-24 19:32:25 +000044 static const unsigned InvalidArgIndex = UINT_MAX;
45 /// Denotes the return vale.
46 static const unsigned ReturnValueIndex = UINT_MAX - 1;
Anna Zaks0244cd72012-01-14 02:48:40 +000047
Ahmed Charlesb8984322014-03-07 20:03:18 +000048 mutable std::unique_ptr<BugType> BT;
Anna Zaks5d324e52012-01-18 02:45:07 +000049 inline void initBugType() const {
50 if (!BT)
Alexander Kornienko4aca9b12014-02-11 21:49:21 +000051 BT.reset(new BugType(this, "Use of Untrusted Data", "Untrusted Data"));
Anna Zaks5d324e52012-01-18 02:45:07 +000052 }
Anna Zaks457c6872011-11-18 02:26:36 +000053
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000054 /// Catch taint related bugs. Check if tainted data is passed to a
Anna Zaksb3fa8d72012-01-12 02:22:34 +000055 /// system call etc.
Anna Zaks126a2ef2012-01-07 02:33:10 +000056 bool checkPre(const CallExpr *CE, CheckerContext &C) const;
57
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000058 /// Add taint sources on a pre-visit.
Anna Zaksb3fa8d72012-01-12 02:22:34 +000059 void addSourcesPre(const CallExpr *CE, CheckerContext &C) const;
60
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000061 /// Propagate taint generated at pre-visit.
Anna Zaksb3fa8d72012-01-12 02:22:34 +000062 bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const;
63
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000064 /// Add taint sources on a post visit.
Anna Zaksb3fa8d72012-01-12 02:22:34 +000065 void addSourcesPost(const CallExpr *CE, CheckerContext &C) const;
66
Anna Zaksbf740512012-01-24 19:32:25 +000067 /// Check if the region the expression evaluates to is the standard input,
68 /// and thus, is tainted.
69 static bool isStdin(const Expr *E, CheckerContext &C);
70
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000071 /// Given a pointer argument, return the value it points to.
Artem Dergacheveed7a312017-05-29 15:42:56 +000072 static Optional<SVal> getPointedToSVal(CheckerContext &C, const Expr *Arg);
Anna Zaks5c5bf9b2011-11-16 19:58:13 +000073
Anna Zaks3b0ab202011-12-17 00:26:34 +000074 /// Functions defining the attack surface.
Artem Dergachevb68cb542018-12-19 23:35:08 +000075 typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(
76 const CallExpr *, CheckerContext &C) const;
Ted Kremenek49b1e382012-01-26 21:29:00 +000077 ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
78 ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
79 ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks3b0ab202011-12-17 00:26:34 +000080
81 /// Taint the scanned input if the file is tainted.
Ted Kremenek49b1e382012-01-26 21:29:00 +000082 ProgramStateRef preFscanf(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks5c5bf9b2011-11-16 19:58:13 +000083
Anna Zaks126a2ef2012-01-07 02:33:10 +000084 /// Check for CWE-134: Uncontrolled Format String.
Anna Zaks0244cd72012-01-14 02:48:40 +000085 static const char MsgUncontrolledFormatString[];
Anna Zaks126a2ef2012-01-07 02:33:10 +000086 bool checkUncontrolledFormatString(const CallExpr *CE,
87 CheckerContext &C) const;
88
Anna Zaks0244cd72012-01-14 02:48:40 +000089 /// Check for:
90 /// CERT/STR02-C. "Sanitize data passed to complex subsystems"
91 /// CWE-78, "Failure to Sanitize Data into an OS Command"
92 static const char MsgSanitizeSystemArgs[];
93 bool checkSystemCall(const CallExpr *CE, StringRef Name,
94 CheckerContext &C) const;
Anna Zaks3b0ab202011-12-17 00:26:34 +000095
Anna Zaks560dbe92012-01-18 02:45:11 +000096 /// Check if tainted data is used as a buffer size ins strn.. functions,
97 /// and allocators.
98 static const char MsgTaintedBufferSize[];
99 bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
100 CheckerContext &C) const;
101
Anna Zaks0244cd72012-01-14 02:48:40 +0000102 /// Generate a report if the expression is tainted or points to tainted data.
103 bool generateReportIfTainted(const Expr *E, const char Msg[],
104 CheckerContext &C) const;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000105
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000106 typedef SmallVector<unsigned, 2> ArgVector;
Anna Zaks3b0ab202011-12-17 00:26:34 +0000107
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000108 /// A struct used to specify taint propagation rules for a function.
Anna Zaks3666d2c2012-01-17 00:37:02 +0000109 ///
110 /// If any of the possible taint source arguments is tainted, all of the
111 /// destination arguments should also be tainted. Use InvalidArgIndex in the
112 /// src list to specify that all of the arguments can introduce taint. Use
113 /// InvalidArgIndex in the dst arguments to signify that all the non-const
114 /// pointer and reference arguments might be tainted on return. If
115 /// ReturnValueIndex is added to the dst list, the return value will be
116 /// tainted.
117 struct TaintPropagationRule {
118 /// List of arguments which can be taint sources and should be checked.
119 ArgVector SrcArgs;
120 /// List of arguments which should be tainted on function return.
121 ArgVector DstArgs;
Anna Zaks5d324e52012-01-18 02:45:07 +0000122 // TODO: Check if using other data structures would be more optimal.
Anna Zaks3666d2c2012-01-17 00:37:02 +0000123
124 TaintPropagationRule() {}
125
Artem Dergachevb68cb542018-12-19 23:35:08 +0000126 TaintPropagationRule(unsigned SArg, unsigned DArg, bool TaintRet = false) {
Anna Zaks3666d2c2012-01-17 00:37:02 +0000127 SrcArgs.push_back(SArg);
128 DstArgs.push_back(DArg);
Anna Zaks5d324e52012-01-18 02:45:07 +0000129 if (TaintRet)
130 DstArgs.push_back(ReturnValueIndex);
Anna Zaks3666d2c2012-01-17 00:37:02 +0000131 }
132
Artem Dergachevb68cb542018-12-19 23:35:08 +0000133 TaintPropagationRule(unsigned SArg1, unsigned SArg2, unsigned DArg,
134 bool TaintRet = false) {
Anna Zaks5d324e52012-01-18 02:45:07 +0000135 SrcArgs.push_back(SArg1);
136 SrcArgs.push_back(SArg2);
137 DstArgs.push_back(DArg);
138 if (TaintRet)
139 DstArgs.push_back(ReturnValueIndex);
140 }
141
142 /// Get the propagation rule for a given function.
143 static TaintPropagationRule
Artem Dergachevb68cb542018-12-19 23:35:08 +0000144 getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
145 CheckerContext &C);
Anna Zaks5d324e52012-01-18 02:45:07 +0000146
Anna Zaks3666d2c2012-01-17 00:37:02 +0000147 inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
Artem Dergachevb68cb542018-12-19 23:35:08 +0000148 inline void addDstArg(unsigned A) { DstArgs.push_back(A); }
Anna Zaks3666d2c2012-01-17 00:37:02 +0000149
Anna Zaks5d324e52012-01-18 02:45:07 +0000150 inline bool isNull() const { return SrcArgs.empty(); }
151
152 inline bool isDestinationArgument(unsigned ArgNum) const {
Artem Dergachevb68cb542018-12-19 23:35:08 +0000153 return (std::find(DstArgs.begin(), DstArgs.end(), ArgNum) !=
154 DstArgs.end());
Anna Zaks5d324e52012-01-18 02:45:07 +0000155 }
Anna Zaks3666d2c2012-01-17 00:37:02 +0000156
Anna Zaksbf740512012-01-24 19:32:25 +0000157 static inline bool isTaintedOrPointsToTainted(const Expr *E,
Ted Kremenek49b1e382012-01-26 21:29:00 +0000158 ProgramStateRef State,
Anna Zaksbf740512012-01-24 19:32:25 +0000159 CheckerContext &C) {
Artem Dergacheveed7a312017-05-29 15:42:56 +0000160 if (State->isTainted(E, C.getLocationContext()) || isStdin(E, C))
161 return true;
162
163 if (!E->getType().getTypePtr()->isPointerType())
164 return false;
165
166 Optional<SVal> V = getPointedToSVal(C, E);
167 return (V && State->isTainted(*V));
Anna Zaksbf740512012-01-24 19:32:25 +0000168 }
169
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000170 /// Pre-process a function which propagates taint according to the
Anna Zaks7f6a6b72012-01-18 02:45:13 +0000171 /// taint rule.
Ted Kremenek49b1e382012-01-26 21:29:00 +0000172 ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks7f6a6b72012-01-18 02:45:13 +0000173 };
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000174};
Anna Zaks5d324e52012-01-18 02:45:07 +0000175
176const unsigned GenericTaintChecker::ReturnValueIndex;
177const unsigned GenericTaintChecker::InvalidArgIndex;
178
Anna Zaks0244cd72012-01-14 02:48:40 +0000179const char GenericTaintChecker::MsgUncontrolledFormatString[] =
Artem Dergachevb68cb542018-12-19 23:35:08 +0000180 "Untrusted data is used as a format string "
181 "(CWE-134: Uncontrolled Format String)";
Anna Zaks0244cd72012-01-14 02:48:40 +0000182
183const char GenericTaintChecker::MsgSanitizeSystemArgs[] =
Artem Dergachevb68cb542018-12-19 23:35:08 +0000184 "Untrusted data is passed to a system call "
185 "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
Anna Zaks560dbe92012-01-18 02:45:11 +0000186
187const char GenericTaintChecker::MsgTaintedBufferSize[] =
Artem Dergachevb68cb542018-12-19 23:35:08 +0000188 "Untrusted data is used to specify the buffer size "
189 "(CERT/STR31-C. Guarantee that storage for strings has sufficient space "
190 "for "
191 "character data and the null terminator)";
Anna Zaks560dbe92012-01-18 02:45:11 +0000192
193} // end of anonymous namespace
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000194
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000195/// A set which is used to pass information from call pre-visit instruction
196/// to the call post-visit. The values are unsigned integers, which are either
197/// ReturnValueIndex, or indexes of the pointer/reference argument, which
198/// points to data, which should be tainted on return.
Jordan Rose0c153cb2012-11-02 01:54:06 +0000199REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned)
Anna Zaks3b0ab202011-12-17 00:26:34 +0000200
Anna Zaks5d324e52012-01-18 02:45:07 +0000201GenericTaintChecker::TaintPropagationRule
202GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
Artem Dergachevb68cb542018-12-19 23:35:08 +0000203 const FunctionDecl *FDecl, StringRef Name, CheckerContext &C) {
Enrico Pertoso4432d872015-06-03 09:10:58 +0000204 // TODO: Currently, we might lose precision here: we always mark a return
Anna Zaksbf740512012-01-24 19:32:25 +0000205 // value as tainted even if it's just a pointer, pointing to tainted data.
206
Anna Zaks5d324e52012-01-18 02:45:07 +0000207 // Check for exact name match for functions without builtin substitutes.
Artem Dergachevb68cb542018-12-19 23:35:08 +0000208 TaintPropagationRule Rule =
209 llvm::StringSwitch<TaintPropagationRule>(Name)
210 .Case("atoi", TaintPropagationRule(0, ReturnValueIndex))
211 .Case("atol", TaintPropagationRule(0, ReturnValueIndex))
212 .Case("atoll", TaintPropagationRule(0, ReturnValueIndex))
213 .Case("getc", TaintPropagationRule(0, ReturnValueIndex))
214 .Case("fgetc", TaintPropagationRule(0, ReturnValueIndex))
215 .Case("getc_unlocked", TaintPropagationRule(0, ReturnValueIndex))
216 .Case("getw", TaintPropagationRule(0, ReturnValueIndex))
217 .Case("toupper", TaintPropagationRule(0, ReturnValueIndex))
218 .Case("tolower", TaintPropagationRule(0, ReturnValueIndex))
219 .Case("strchr", TaintPropagationRule(0, ReturnValueIndex))
220 .Case("strrchr", TaintPropagationRule(0, ReturnValueIndex))
221 .Case("read", TaintPropagationRule(0, 2, 1, true))
222 .Case("pread", TaintPropagationRule(InvalidArgIndex, 1, true))
223 .Case("gets", TaintPropagationRule(InvalidArgIndex, 0, true))
224 .Case("fgets", TaintPropagationRule(2, 0, true))
225 .Case("getline", TaintPropagationRule(2, 0))
226 .Case("getdelim", TaintPropagationRule(3, 0))
227 .Case("fgetln", TaintPropagationRule(0, ReturnValueIndex))
228 .Default(TaintPropagationRule());
Anna Zaks5d324e52012-01-18 02:45:07 +0000229
230 if (!Rule.isNull())
231 return Rule;
232
233 // Check if it's one of the memory setting/copying functions.
234 // This check is specialized but faster then calling isCLibraryFunction.
235 unsigned BId = 0;
Artem Dergachevb68cb542018-12-19 23:35:08 +0000236 if ((BId = FDecl->getMemoryFunctionKind()))
237 switch (BId) {
Anna Zaks5d324e52012-01-18 02:45:07 +0000238 case Builtin::BImemcpy:
239 case Builtin::BImemmove:
240 case Builtin::BIstrncpy:
241 case Builtin::BIstrncat:
242 return TaintPropagationRule(1, 2, 0, true);
Anna Zaks5d324e52012-01-18 02:45:07 +0000243 case Builtin::BIstrlcpy:
244 case Builtin::BIstrlcat:
245 return TaintPropagationRule(1, 2, 0, false);
Anna Zaks5d324e52012-01-18 02:45:07 +0000246 case Builtin::BIstrndup:
247 return TaintPropagationRule(0, 1, ReturnValueIndex);
Anna Zaks5d324e52012-01-18 02:45:07 +0000248
249 default:
250 break;
251 };
252
253 // Process all other functions which could be defined as builtins.
254 if (Rule.isNull()) {
255 if (C.isCLibraryFunction(FDecl, "snprintf") ||
256 C.isCLibraryFunction(FDecl, "sprintf"))
257 return TaintPropagationRule(InvalidArgIndex, 0, true);
258 else if (C.isCLibraryFunction(FDecl, "strcpy") ||
259 C.isCLibraryFunction(FDecl, "stpcpy") ||
260 C.isCLibraryFunction(FDecl, "strcat"))
261 return TaintPropagationRule(1, 0, true);
262 else if (C.isCLibraryFunction(FDecl, "bcopy"))
263 return TaintPropagationRule(0, 2, 1, false);
264 else if (C.isCLibraryFunction(FDecl, "strdup") ||
265 C.isCLibraryFunction(FDecl, "strdupa"))
266 return TaintPropagationRule(0, ReturnValueIndex);
Anna Zaks560dbe92012-01-18 02:45:11 +0000267 else if (C.isCLibraryFunction(FDecl, "wcsdup"))
268 return TaintPropagationRule(0, ReturnValueIndex);
Anna Zaks5d324e52012-01-18 02:45:07 +0000269 }
270
271 // Skipping the following functions, since they might be used for cleansing
272 // or smart memory copy:
Benjamin Kramer474261a2012-06-02 10:20:41 +0000273 // - memccpy - copying until hitting a special character.
Anna Zaks5d324e52012-01-18 02:45:07 +0000274
275 return TaintPropagationRule();
Anna Zaks457c6872011-11-18 02:26:36 +0000276}
277
Anna Zaks3b0ab202011-12-17 00:26:34 +0000278void GenericTaintChecker::checkPreStmt(const CallExpr *CE,
279 CheckerContext &C) const {
Anna Zaks126a2ef2012-01-07 02:33:10 +0000280 // Check for errors first.
281 if (checkPre(CE, C))
282 return;
Anna Zaks3b0ab202011-12-17 00:26:34 +0000283
Anna Zaks126a2ef2012-01-07 02:33:10 +0000284 // Add taint second.
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000285 addSourcesPre(CE, C);
Anna Zaks126a2ef2012-01-07 02:33:10 +0000286}
287
288void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
289 CheckerContext &C) const {
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000290 if (propagateFromPre(CE, C))
291 return;
292 addSourcesPost(CE, C);
Anna Zaks126a2ef2012-01-07 02:33:10 +0000293}
294
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000295void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
296 CheckerContext &C) const {
Craig Topper0dbb7832014-05-27 02:45:47 +0000297 ProgramStateRef State = nullptr;
Anna Zaks5d324e52012-01-18 02:45:07 +0000298 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
Jordan Rose6cd16c52012-07-10 23:13:01 +0000299 if (!FDecl || FDecl->getKind() != Decl::Function)
300 return;
301
Anna Zaks5d324e52012-01-18 02:45:07 +0000302 StringRef Name = C.getCalleeName(FDecl);
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000303 if (Name.empty())
304 return;
Anna Zaks3666d2c2012-01-17 00:37:02 +0000305
Anna Zaks5d324e52012-01-18 02:45:07 +0000306 // First, try generating a propagation rule for this function.
307 TaintPropagationRule Rule =
Artem Dergachevb68cb542018-12-19 23:35:08 +0000308 TaintPropagationRule::getTaintPropagationRule(FDecl, Name, C);
Anna Zaks3666d2c2012-01-17 00:37:02 +0000309 if (!Rule.isNull()) {
Anna Zaks7f6a6b72012-01-18 02:45:13 +0000310 State = Rule.process(CE, C);
Anna Zaks3666d2c2012-01-17 00:37:02 +0000311 if (!State)
312 return;
313 C.addTransition(State);
Anna Zaks5d324e52012-01-18 02:45:07 +0000314 return;
Anna Zaks3666d2c2012-01-17 00:37:02 +0000315 }
316
Anna Zaks5d324e52012-01-18 02:45:07 +0000317 // Otherwise, check if we have custom pre-processing implemented.
Anna Zaks3b0ab202011-12-17 00:26:34 +0000318 FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
Artem Dergachevb68cb542018-12-19 23:35:08 +0000319 .Case("fscanf", &GenericTaintChecker::preFscanf)
320 .Default(nullptr);
Anna Zaks3b0ab202011-12-17 00:26:34 +0000321 // Check and evaluate the call.
322 if (evalFunction)
323 State = (this->*evalFunction)(CE, C);
324 if (!State)
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000325 return;
Anna Zaks3b0ab202011-12-17 00:26:34 +0000326 C.addTransition(State);
327}
328
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000329bool GenericTaintChecker::propagateFromPre(const CallExpr *CE,
330 CheckerContext &C) const {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000331 ProgramStateRef State = C.getState();
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000332
333 // Depending on what was tainted at pre-visit, we determined a set of
334 // arguments which should be tainted after the function returns. These are
335 // stored in the state as TaintArgsOnPostVisit set.
Jordan Rose0c153cb2012-11-02 01:54:06 +0000336 TaintArgsOnPostVisitTy TaintArgs = State->get<TaintArgsOnPostVisit>();
Anna Zaksbf740512012-01-24 19:32:25 +0000337 if (TaintArgs.isEmpty())
338 return false;
339
Artem Dergachevb68cb542018-12-19 23:35:08 +0000340 for (llvm::ImmutableSet<unsigned>::iterator I = TaintArgs.begin(),
341 E = TaintArgs.end();
342 I != E; ++I) {
343 unsigned ArgNum = *I;
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000344
345 // Special handling for the tainted return value.
346 if (ArgNum == ReturnValueIndex) {
347 State = State->addTaint(CE, C.getLocationContext());
348 continue;
349 }
350
351 // The arguments are pointer arguments. The data they are pointing at is
352 // tainted after the call.
Anna Zaksb508d292012-04-10 23:41:11 +0000353 if (CE->getNumArgs() < (ArgNum + 1))
354 return false;
Artem Dergachevb68cb542018-12-19 23:35:08 +0000355 const Expr *Arg = CE->getArg(ArgNum);
Artem Dergacheveed7a312017-05-29 15:42:56 +0000356 Optional<SVal> V = getPointedToSVal(C, Arg);
357 if (V)
358 State = State->addTaint(*V);
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000359 }
360
361 // Clear up the taint info from the state.
362 State = State->remove<TaintArgsOnPostVisit>();
363
364 if (State != C.getState()) {
365 C.addTransition(State);
366 return true;
367 }
368 return false;
369}
370
371void GenericTaintChecker::addSourcesPost(const CallExpr *CE,
372 CheckerContext &C) const {
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000373 // Define the attack surface.
374 // Set the evaluation function by switching on the callee name.
Jordan Rose6cd16c52012-07-10 23:13:01 +0000375 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
376 if (!FDecl || FDecl->getKind() != Decl::Function)
377 return;
378
379 StringRef Name = C.getCalleeName(FDecl);
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000380 if (Name.empty())
381 return;
Artem Dergachevb68cb542018-12-19 23:35:08 +0000382 FnCheck evalFunction =
383 llvm::StringSwitch<FnCheck>(Name)
384 .Case("scanf", &GenericTaintChecker::postScanf)
385 // TODO: Add support for vfscanf & family.
386 .Case("getchar", &GenericTaintChecker::postRetTaint)
387 .Case("getchar_unlocked", &GenericTaintChecker::postRetTaint)
388 .Case("getenv", &GenericTaintChecker::postRetTaint)
389 .Case("fopen", &GenericTaintChecker::postRetTaint)
390 .Case("fdopen", &GenericTaintChecker::postRetTaint)
391 .Case("freopen", &GenericTaintChecker::postRetTaint)
392 .Case("getch", &GenericTaintChecker::postRetTaint)
393 .Case("wgetch", &GenericTaintChecker::postRetTaint)
394 .Case("socket", &GenericTaintChecker::postSocket)
395 .Default(nullptr);
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000396
397 // If the callee isn't defined, it is not of security concern.
398 // Check and evaluate the call.
Craig Topper0dbb7832014-05-27 02:45:47 +0000399 ProgramStateRef State = nullptr;
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000400 if (evalFunction)
Anna Zaks3b0ab202011-12-17 00:26:34 +0000401 State = (this->*evalFunction)(CE, C);
402 if (!State)
403 return;
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000404
Anna Zaks3b0ab202011-12-17 00:26:34 +0000405 C.addTransition(State);
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000406}
Anna Zaks457c6872011-11-18 02:26:36 +0000407
Artem Dergachevb68cb542018-12-19 23:35:08 +0000408bool GenericTaintChecker::checkPre(const CallExpr *CE,
409 CheckerContext &C) const {
Anna Zaks126a2ef2012-01-07 02:33:10 +0000410
411 if (checkUncontrolledFormatString(CE, C))
412 return true;
413
Anna Zaks560dbe92012-01-18 02:45:11 +0000414 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
Jordan Rose6cd16c52012-07-10 23:13:01 +0000415 if (!FDecl || FDecl->getKind() != Decl::Function)
416 return false;
417
Anna Zaks560dbe92012-01-18 02:45:11 +0000418 StringRef Name = C.getCalleeName(FDecl);
Anna Zaks0244cd72012-01-14 02:48:40 +0000419 if (Name.empty())
420 return false;
421
422 if (checkSystemCall(CE, Name, C))
423 return true;
424
Anna Zaks560dbe92012-01-18 02:45:11 +0000425 if (checkTaintedBufferSize(CE, FDecl, C))
426 return true;
427
Anna Zaks126a2ef2012-01-07 02:33:10 +0000428 return false;
429}
430
Artem Dergacheveed7a312017-05-29 15:42:56 +0000431Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
Artem Dergachev3ef5deb2017-12-12 02:27:55 +0000432 const Expr *Arg) {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000433 ProgramStateRef State = C.getState();
George Karpenkovd703ec92018-01-17 20:27:29 +0000434 SVal AddrVal = C.getSVal(Arg->IgnoreParens());
Anna Zakse48ee502011-12-16 18:28:50 +0000435 if (AddrVal.isUnknownOrUndef())
Artem Dergacheveed7a312017-05-29 15:42:56 +0000436 return None;
Anna Zaks7c96b7d2011-12-11 18:43:40 +0000437
David Blaikie05785d12013-02-20 22:23:23 +0000438 Optional<Loc> AddrLoc = AddrVal.getAs<Loc>();
Anna Zaks7f6a6b72012-01-18 02:45:13 +0000439 if (!AddrLoc)
Artem Dergacheveed7a312017-05-29 15:42:56 +0000440 return None;
Anna Zaks457c6872011-11-18 02:26:36 +0000441
Artem Dergachev3ef5deb2017-12-12 02:27:55 +0000442 QualType ArgTy = Arg->getType().getCanonicalType();
443 if (!ArgTy->isPointerType())
444 return None;
445
446 QualType ValTy = ArgTy->getPointeeType();
447
448 // Do not dereference void pointers. Treat them as byte pointers instead.
449 // FIXME: we might want to consider more than just the first byte.
450 if (ValTy->isVoidType())
451 ValTy = C.getASTContext().CharTy;
452
453 return State->getSVal(*AddrLoc, ValTy);
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000454}
455
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000456ProgramStateRef
Anna Zaks7f6a6b72012-01-18 02:45:13 +0000457GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
458 CheckerContext &C) const {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000459 ProgramStateRef State = C.getState();
Anna Zaks3666d2c2012-01-17 00:37:02 +0000460
461 // Check for taint in arguments.
462 bool IsTainted = false;
Artem Dergachevb68cb542018-12-19 23:35:08 +0000463 for (ArgVector::const_iterator I = SrcArgs.begin(), E = SrcArgs.end(); I != E;
464 ++I) {
Anna Zaks3666d2c2012-01-17 00:37:02 +0000465 unsigned ArgNum = *I;
466
467 if (ArgNum == InvalidArgIndex) {
Anna Zaks5d324e52012-01-18 02:45:07 +0000468 // Check if any of the arguments is tainted, but skip the
469 // destination arguments.
470 for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
Anna Zaks7f6a6b72012-01-18 02:45:13 +0000471 if (isDestinationArgument(i))
Anna Zaks5d324e52012-01-18 02:45:07 +0000472 continue;
Anna Zaksbf740512012-01-24 19:32:25 +0000473 if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(i), State, C)))
Anna Zaks3666d2c2012-01-17 00:37:02 +0000474 break;
Anna Zaks5d324e52012-01-18 02:45:07 +0000475 }
Anna Zaks3666d2c2012-01-17 00:37:02 +0000476 break;
477 }
478
Anna Zaksb508d292012-04-10 23:41:11 +0000479 if (CE->getNumArgs() < (ArgNum + 1))
480 return State;
Anna Zaksbf740512012-01-24 19:32:25 +0000481 if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(ArgNum), State, C)))
Anna Zaks3666d2c2012-01-17 00:37:02 +0000482 break;
483 }
484 if (!IsTainted)
485 return State;
486
487 // Mark the arguments which should be tainted after the function returns.
Artem Dergachevb68cb542018-12-19 23:35:08 +0000488 for (ArgVector::const_iterator I = DstArgs.begin(), E = DstArgs.end(); I != E;
489 ++I) {
Anna Zaks3666d2c2012-01-17 00:37:02 +0000490 unsigned ArgNum = *I;
491
492 // Should we mark all arguments as tainted?
493 if (ArgNum == InvalidArgIndex) {
494 // For all pointer and references that were passed in:
495 // If they are not pointing to const data, mark data as tainted.
496 // TODO: So far we are just going one level down; ideally we'd need to
497 // recurse here.
498 for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
499 const Expr *Arg = CE->getArg(i);
500 // Process pointer argument.
501 const Type *ArgTy = Arg->getType().getTypePtr();
502 QualType PType = ArgTy->getPointeeType();
Artem Dergachevb68cb542018-12-19 23:35:08 +0000503 if ((!PType.isNull() && !PType.isConstQualified()) ||
504 (ArgTy->isReferenceType() && !Arg->getType().isConstQualified()))
Anna Zaks3666d2c2012-01-17 00:37:02 +0000505 State = State->add<TaintArgsOnPostVisit>(i);
506 }
507 continue;
508 }
509
510 // Should mark the return value?
511 if (ArgNum == ReturnValueIndex) {
512 State = State->add<TaintArgsOnPostVisit>(ReturnValueIndex);
513 continue;
514 }
515
516 // Mark the given argument.
517 assert(ArgNum < CE->getNumArgs());
518 State = State->add<TaintArgsOnPostVisit>(ArgNum);
519 }
520
521 return State;
522}
523
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000524// If argument 0 (file descriptor) is tainted, all arguments except for arg 0
525// and arg 1 should get taint.
Ted Kremenek49b1e382012-01-26 21:29:00 +0000526ProgramStateRef GenericTaintChecker::preFscanf(const CallExpr *CE,
Artem Dergachevb68cb542018-12-19 23:35:08 +0000527 CheckerContext &C) const {
Anna Zaks3b0ab202011-12-17 00:26:34 +0000528 assert(CE->getNumArgs() >= 2);
Ted Kremenek49b1e382012-01-26 21:29:00 +0000529 ProgramStateRef State = C.getState();
Anna Zaks3b0ab202011-12-17 00:26:34 +0000530
531 // Check is the file descriptor is tainted.
Ted Kremenek632e3b72012-01-06 22:09:28 +0000532 if (State->isTainted(CE->getArg(0), C.getLocationContext()) ||
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000533 isStdin(CE->getArg(0), C)) {
534 // All arguments except for the first two should get taint.
535 for (unsigned int i = 2; i < CE->getNumArgs(); ++i)
Artem Dergachevb68cb542018-12-19 23:35:08 +0000536 State = State->add<TaintArgsOnPostVisit>(i);
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000537 return State;
538 }
539
Craig Topper0dbb7832014-05-27 02:45:47 +0000540 return nullptr;
Anna Zaks3b0ab202011-12-17 00:26:34 +0000541}
542
Anna Zaks3b754b22012-01-20 00:11:19 +0000543// If argument 0(protocol domain) is network, the return value should get taint.
Ted Kremenek49b1e382012-01-26 21:29:00 +0000544ProgramStateRef GenericTaintChecker::postSocket(const CallExpr *CE,
Anna Zaksb508d292012-04-10 23:41:11 +0000545 CheckerContext &C) const {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000546 ProgramStateRef State = C.getState();
Anna Zaksb508d292012-04-10 23:41:11 +0000547 if (CE->getNumArgs() < 3)
548 return State;
Anna Zaks3b754b22012-01-20 00:11:19 +0000549
550 SourceLocation DomLoc = CE->getArg(0)->getExprLoc();
551 StringRef DomName = C.getMacroNameOrSpelling(DomLoc);
552 // White list the internal communication protocols.
553 if (DomName.equals("AF_SYSTEM") || DomName.equals("AF_LOCAL") ||
554 DomName.equals("AF_UNIX") || DomName.equals("AF_RESERVED_36"))
555 return State;
556 State = State->addTaint(CE, C.getLocationContext());
557 return State;
558}
559
Ted Kremenek49b1e382012-01-26 21:29:00 +0000560ProgramStateRef GenericTaintChecker::postScanf(const CallExpr *CE,
Artem Dergachevb68cb542018-12-19 23:35:08 +0000561 CheckerContext &C) const {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000562 ProgramStateRef State = C.getState();
Anna Zaksb508d292012-04-10 23:41:11 +0000563 if (CE->getNumArgs() < 2)
564 return State;
565
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000566 // All arguments except for the very first one should get taint.
567 for (unsigned int i = 1; i < CE->getNumArgs(); ++i) {
568 // The arguments are pointer arguments. The data they are pointing at is
569 // tainted after the call.
Artem Dergachevb68cb542018-12-19 23:35:08 +0000570 const Expr *Arg = CE->getArg(i);
Artem Dergacheveed7a312017-05-29 15:42:56 +0000571 Optional<SVal> V = getPointedToSVal(C, Arg);
572 if (V)
573 State = State->addTaint(*V);
Anna Zakseefc0e92011-12-14 00:56:02 +0000574 }
Anna Zaks3b0ab202011-12-17 00:26:34 +0000575 return State;
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000576}
577
Ted Kremenek49b1e382012-01-26 21:29:00 +0000578ProgramStateRef GenericTaintChecker::postRetTaint(const CallExpr *CE,
Anna Zaksb508d292012-04-10 23:41:11 +0000579 CheckerContext &C) const {
Ted Kremenek632e3b72012-01-06 22:09:28 +0000580 return C.getState()->addTaint(CE, C.getLocationContext());
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000581}
582
Anna Zaksbf740512012-01-24 19:32:25 +0000583bool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000584 ProgramStateRef State = C.getState();
George Karpenkovd703ec92018-01-17 20:27:29 +0000585 SVal Val = C.getSVal(E);
Anna Zaks099fe3f2011-12-14 00:56:18 +0000586
Anna Zakse48ee502011-12-16 18:28:50 +0000587 // stdin is a pointer, so it would be a region.
588 const MemRegion *MemReg = Val.getAsRegion();
589
590 // The region should be symbolic, we do not know it's value.
591 const SymbolicRegion *SymReg = dyn_cast_or_null<SymbolicRegion>(MemReg);
592 if (!SymReg)
Anna Zaks099fe3f2011-12-14 00:56:18 +0000593 return false;
594
Anna Zakse48ee502011-12-16 18:28:50 +0000595 // Get it's symbol and find the declaration region it's pointing to.
Artem Dergachevb68cb542018-12-19 23:35:08 +0000596 const SymbolRegionValue *Sm =
597 dyn_cast<SymbolRegionValue>(SymReg->getSymbol());
Anna Zakse48ee502011-12-16 18:28:50 +0000598 if (!Sm)
599 return false;
600 const DeclRegion *DeclReg = dyn_cast_or_null<DeclRegion>(Sm->getRegion());
601 if (!DeclReg)
602 return false;
Anna Zaks099fe3f2011-12-14 00:56:18 +0000603
Anna Zakse48ee502011-12-16 18:28:50 +0000604 // This region corresponds to a declaration, find out if it's a global/extern
605 // variable named stdin with the proper type.
606 if (const VarDecl *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) {
607 D = D->getCanonicalDecl();
608 if ((D->getName().find("stdin") != StringRef::npos) && D->isExternC())
Artem Dergachevb68cb542018-12-19 23:35:08 +0000609 if (const PointerType *PtrTy =
Anna Zakse48ee502011-12-16 18:28:50 +0000610 dyn_cast<PointerType>(D->getType().getTypePtr()))
Artem Dergachevb68cb542018-12-19 23:35:08 +0000611 if (PtrTy->getPointeeType().getCanonicalType() ==
612 C.getASTContext().getFILEType().getCanonicalType())
613 return true;
Anna Zakse48ee502011-12-16 18:28:50 +0000614 }
Anna Zaks099fe3f2011-12-14 00:56:18 +0000615 return false;
616}
617
Anna Zaks126a2ef2012-01-07 02:33:10 +0000618static bool getPrintfFormatArgumentNum(const CallExpr *CE,
619 const CheckerContext &C,
620 unsigned int &ArgNum) {
621 // Find if the function contains a format string argument.
622 // Handles: fprintf, printf, sprintf, snprintf, vfprintf, vprintf, vsprintf,
623 // vsnprintf, syslog, custom annotated functions.
624 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
625 if (!FDecl)
626 return false;
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +0000627 for (const auto *Format : FDecl->specific_attrs<FormatAttr>()) {
Anna Zaks126a2ef2012-01-07 02:33:10 +0000628 ArgNum = Format->getFormatIdx() - 1;
Artem Dergachevb68cb542018-12-19 23:35:08 +0000629 if ((Format->getType()->getName() == "printf") && CE->getNumArgs() > ArgNum)
Anna Zaks126a2ef2012-01-07 02:33:10 +0000630 return true;
631 }
632
633 // Or if a function is named setproctitle (this is a heuristic).
634 if (C.getCalleeName(CE).find("setproctitle") != StringRef::npos) {
635 ArgNum = 0;
636 return true;
637 }
638
639 return false;
640}
641
Anna Zaks0244cd72012-01-14 02:48:40 +0000642bool GenericTaintChecker::generateReportIfTainted(const Expr *E,
643 const char Msg[],
644 CheckerContext &C) const {
645 assert(E);
646
647 // Check for taint.
Ted Kremenek49b1e382012-01-26 21:29:00 +0000648 ProgramStateRef State = C.getState();
Artem Dergacheveed7a312017-05-29 15:42:56 +0000649 Optional<SVal> PointedToSVal = getPointedToSVal(C, E);
Anna Zaksd4e43ae2017-03-09 00:01:07 +0000650 SVal TaintedSVal;
Artem Dergacheveed7a312017-05-29 15:42:56 +0000651 if (PointedToSVal && State->isTainted(*PointedToSVal))
652 TaintedSVal = *PointedToSVal;
Anna Zaksd4e43ae2017-03-09 00:01:07 +0000653 else if (State->isTainted(E, C.getLocationContext()))
654 TaintedSVal = C.getSVal(E);
655 else
Anna Zaks0244cd72012-01-14 02:48:40 +0000656 return false;
657
658 // Generate diagnostic.
Devin Coughline39bd402015-09-16 22:03:05 +0000659 if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
Anna Zaks0244cd72012-01-14 02:48:40 +0000660 initBugType();
Aaron Ballman8d3a7a52015-06-23 13:15:32 +0000661 auto report = llvm::make_unique<BugReport>(*BT, Msg, N);
Anna Zaks0244cd72012-01-14 02:48:40 +0000662 report->addRange(E->getSourceRange());
Anna Zaksd4e43ae2017-03-09 00:01:07 +0000663 report->addVisitor(llvm::make_unique<TaintBugVisitor>(TaintedSVal));
Aaron Ballman8d3a7a52015-06-23 13:15:32 +0000664 C.emitReport(std::move(report));
Anna Zaks0244cd72012-01-14 02:48:40 +0000665 return true;
666 }
667 return false;
668}
669
Artem Dergachevb68cb542018-12-19 23:35:08 +0000670bool GenericTaintChecker::checkUncontrolledFormatString(
671 const CallExpr *CE, CheckerContext &C) const {
Anna Zaks126a2ef2012-01-07 02:33:10 +0000672 // Check if the function contains a format string argument.
673 unsigned int ArgNum = 0;
674 if (!getPrintfFormatArgumentNum(CE, C, ArgNum))
675 return false;
676
Artem Dergachevb68cb542018-12-19 23:35:08 +0000677 // If either the format string content or the pointer itself are tainted,
678 // warn.
Alexander Kornienko9c104902015-12-28 13:06:58 +0000679 return generateReportIfTainted(CE->getArg(ArgNum),
680 MsgUncontrolledFormatString, C);
Anna Zaks0244cd72012-01-14 02:48:40 +0000681}
682
Artem Dergachevb68cb542018-12-19 23:35:08 +0000683bool GenericTaintChecker::checkSystemCall(const CallExpr *CE, StringRef Name,
Anna Zaks0244cd72012-01-14 02:48:40 +0000684 CheckerContext &C) const {
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000685 // TODO: It might make sense to run this check on demand. In some cases,
686 // we should check if the environment has been cleansed here. We also might
Anna Zaksbf740512012-01-24 19:32:25 +0000687 // need to know if the user was reset before these calls(seteuid).
Anna Zaks0244cd72012-01-14 02:48:40 +0000688 unsigned ArgNum = llvm::StringSwitch<unsigned>(Name)
Artem Dergachevb68cb542018-12-19 23:35:08 +0000689 .Case("system", 0)
690 .Case("popen", 0)
691 .Case("execl", 0)
692 .Case("execle", 0)
693 .Case("execlp", 0)
694 .Case("execv", 0)
695 .Case("execvp", 0)
696 .Case("execvP", 0)
697 .Case("execve", 0)
698 .Case("dlopen", 0)
699 .Default(UINT_MAX);
Anna Zaks0244cd72012-01-14 02:48:40 +0000700
Anna Zaksb508d292012-04-10 23:41:11 +0000701 if (ArgNum == UINT_MAX || CE->getNumArgs() < (ArgNum + 1))
Anna Zaks0244cd72012-01-14 02:48:40 +0000702 return false;
703
Alexander Kornienko9c104902015-12-28 13:06:58 +0000704 return generateReportIfTainted(CE->getArg(ArgNum), MsgSanitizeSystemArgs, C);
Anna Zaks126a2ef2012-01-07 02:33:10 +0000705}
706
Anna Zaks560dbe92012-01-18 02:45:11 +0000707// TODO: Should this check be a part of the CString checker?
708// If yes, should taint be a global setting?
709bool GenericTaintChecker::checkTaintedBufferSize(const CallExpr *CE,
710 const FunctionDecl *FDecl,
711 CheckerContext &C) const {
712 // If the function has a buffer size argument, set ArgNum.
713 unsigned ArgNum = InvalidArgIndex;
714 unsigned BId = 0;
Artem Dergachevb68cb542018-12-19 23:35:08 +0000715 if ((BId = FDecl->getMemoryFunctionKind()))
716 switch (BId) {
Anna Zaks560dbe92012-01-18 02:45:11 +0000717 case Builtin::BImemcpy:
718 case Builtin::BImemmove:
719 case Builtin::BIstrncpy:
720 ArgNum = 2;
721 break;
722 case Builtin::BIstrndup:
723 ArgNum = 1;
724 break;
725 default:
726 break;
727 };
728
729 if (ArgNum == InvalidArgIndex) {
730 if (C.isCLibraryFunction(FDecl, "malloc") ||
731 C.isCLibraryFunction(FDecl, "calloc") ||
732 C.isCLibraryFunction(FDecl, "alloca"))
733 ArgNum = 0;
734 else if (C.isCLibraryFunction(FDecl, "memccpy"))
735 ArgNum = 3;
736 else if (C.isCLibraryFunction(FDecl, "realloc"))
737 ArgNum = 1;
738 else if (C.isCLibraryFunction(FDecl, "bcopy"))
739 ArgNum = 2;
740 }
741
Alexander Kornienko9c104902015-12-28 13:06:58 +0000742 return ArgNum != InvalidArgIndex && CE->getNumArgs() > ArgNum &&
743 generateReportIfTainted(CE->getArg(ArgNum), MsgTaintedBufferSize, C);
Anna Zaks560dbe92012-01-18 02:45:11 +0000744}
745
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000746void ento::registerGenericTaintChecker(CheckerManager &mgr) {
747 mgr.registerChecker<GenericTaintChecker>();
748}