blob: eeddfddc4d40777a6dcedb4bf5537056bb4a4cbf [file] [log] [blame]
Anna Zaks5c5bf9b2011-11-16 19:58:13 +00001//== GenericTaintChecker.cpp ----------------------------------- -*- C++ -*--=//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Anna Zaks5c5bf9b2011-11-16 19:58:13 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This checker defines the attack surface for generic taint propagation.
10//
11// The taint information produced by it might be useful to other checkers. For
12// example, checkers should report errors which involve tainted data more
13// aggressively, even if the involved symbols are under constrained.
14//
15//===----------------------------------------------------------------------===//
Kristof Umann76a21502018-12-15 16:23:51 +000016#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000017#include "clang/AST/Attr.h"
18#include "clang/Basic/Builtins.h"
19#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
Anna Zaks5c5bf9b2011-11-16 19:58:13 +000020#include "clang/StaticAnalyzer/Core/Checker.h"
21#include "clang/StaticAnalyzer/Core/CheckerManager.h"
22#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
Anna Zaks3b0ab202011-12-17 00:26:34 +000023#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
Anna Zaksb3fa8d72012-01-12 02:22:34 +000024#include <climits>
Artem Dergachev2a5fb122019-01-30 00:06:43 +000025#include <initializer_list>
26#include <utility>
Anna Zaks5c5bf9b2011-11-16 19:58:13 +000027
28using namespace clang;
29using namespace ento;
30
31namespace {
Artem Dergachevb68cb542018-12-19 23:35:08 +000032class GenericTaintChecker
33 : public Checker<check::PostStmt<CallExpr>, check::PreStmt<CallExpr>> {
Anna Zaks3b0ab202011-12-17 00:26:34 +000034public:
Artem Dergachevb68cb542018-12-19 23:35:08 +000035 static void *getTag() {
36 static int Tag;
37 return &Tag;
38 }
Anna Zaks0244cd72012-01-14 02:48:40 +000039
40 void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks0244cd72012-01-14 02:48:40 +000041
42 void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks5c5bf9b2011-11-16 19:58:13 +000043
Anna Zaks3b0ab202011-12-17 00:26:34 +000044private:
Anna Zaksbf740512012-01-24 19:32:25 +000045 static const unsigned InvalidArgIndex = UINT_MAX;
46 /// Denotes the return vale.
47 static const unsigned ReturnValueIndex = UINT_MAX - 1;
Anna Zaks0244cd72012-01-14 02:48:40 +000048
Ahmed Charlesb8984322014-03-07 20:03:18 +000049 mutable std::unique_ptr<BugType> BT;
Artem Dergachev2a5fb122019-01-30 00:06:43 +000050 void initBugType() const {
Anna Zaks5d324e52012-01-18 02:45:07 +000051 if (!BT)
Alexander Kornienko4aca9b12014-02-11 21:49:21 +000052 BT.reset(new BugType(this, "Use of Untrusted Data", "Untrusted Data"));
Anna Zaks5d324e52012-01-18 02:45:07 +000053 }
Anna Zaks457c6872011-11-18 02:26:36 +000054
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000055 /// Catch taint related bugs. Check if tainted data is passed to a
Anna Zaksb3fa8d72012-01-12 02:22:34 +000056 /// system call etc.
Anna Zaks126a2ef2012-01-07 02:33:10 +000057 bool checkPre(const CallExpr *CE, CheckerContext &C) const;
58
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000059 /// Add taint sources on a pre-visit.
Anna Zaksb3fa8d72012-01-12 02:22:34 +000060 void addSourcesPre(const CallExpr *CE, CheckerContext &C) const;
61
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000062 /// Propagate taint generated at pre-visit.
Anna Zaksb3fa8d72012-01-12 02:22:34 +000063 bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const;
64
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000065 /// Add taint sources on a post visit.
Anna Zaksb3fa8d72012-01-12 02:22:34 +000066 void addSourcesPost(const CallExpr *CE, CheckerContext &C) const;
67
Anna Zaksbf740512012-01-24 19:32:25 +000068 /// Check if the region the expression evaluates to is the standard input,
69 /// and thus, is tainted.
70 static bool isStdin(const Expr *E, CheckerContext &C);
71
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000072 /// Given a pointer argument, return the value it points to.
Artem Dergacheveed7a312017-05-29 15:42:56 +000073 static Optional<SVal> getPointedToSVal(CheckerContext &C, const Expr *Arg);
Anna Zaks5c5bf9b2011-11-16 19:58:13 +000074
Anna Zaks3b0ab202011-12-17 00:26:34 +000075 /// Functions defining the attack surface.
Artem Dergachev2a5fb122019-01-30 00:06:43 +000076 using FnCheck = ProgramStateRef (GenericTaintChecker::*)(
Artem Dergachevb68cb542018-12-19 23:35:08 +000077 const CallExpr *, CheckerContext &C) const;
Ted Kremenek49b1e382012-01-26 21:29:00 +000078 ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
79 ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
80 ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks3b0ab202011-12-17 00:26:34 +000081
82 /// Taint the scanned input if the file is tainted.
Ted Kremenek49b1e382012-01-26 21:29:00 +000083 ProgramStateRef preFscanf(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks5c5bf9b2011-11-16 19:58:13 +000084
Anna Zaks126a2ef2012-01-07 02:33:10 +000085 /// Check for CWE-134: Uncontrolled Format String.
Anna Zaks0244cd72012-01-14 02:48:40 +000086 static const char MsgUncontrolledFormatString[];
Anna Zaks126a2ef2012-01-07 02:33:10 +000087 bool checkUncontrolledFormatString(const CallExpr *CE,
88 CheckerContext &C) const;
89
Anna Zaks0244cd72012-01-14 02:48:40 +000090 /// Check for:
91 /// CERT/STR02-C. "Sanitize data passed to complex subsystems"
92 /// CWE-78, "Failure to Sanitize Data into an OS Command"
93 static const char MsgSanitizeSystemArgs[];
94 bool checkSystemCall(const CallExpr *CE, StringRef Name,
95 CheckerContext &C) const;
Anna Zaks3b0ab202011-12-17 00:26:34 +000096
Anna Zaks560dbe92012-01-18 02:45:11 +000097 /// Check if tainted data is used as a buffer size ins strn.. functions,
98 /// and allocators.
99 static const char MsgTaintedBufferSize[];
100 bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
101 CheckerContext &C) const;
102
Anna Zaks0244cd72012-01-14 02:48:40 +0000103 /// Generate a report if the expression is tainted or points to tainted data.
104 bool generateReportIfTainted(const Expr *E, const char Msg[],
105 CheckerContext &C) const;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000106
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000107 using ArgVector = SmallVector<unsigned, 2>;
Anna Zaks3b0ab202011-12-17 00:26:34 +0000108
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000109 /// A struct used to specify taint propagation rules for a function.
Anna Zaks3666d2c2012-01-17 00:37:02 +0000110 ///
111 /// If any of the possible taint source arguments is tainted, all of the
112 /// destination arguments should also be tainted. Use InvalidArgIndex in the
113 /// src list to specify that all of the arguments can introduce taint. Use
114 /// InvalidArgIndex in the dst arguments to signify that all the non-const
115 /// pointer and reference arguments might be tainted on return. If
116 /// ReturnValueIndex is added to the dst list, the return value will be
117 /// tainted.
118 struct TaintPropagationRule {
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000119 enum class VariadicType { None, Src, Dst };
120
Anna Zaks3666d2c2012-01-17 00:37:02 +0000121 /// List of arguments which can be taint sources and should be checked.
122 ArgVector SrcArgs;
123 /// List of arguments which should be tainted on function return.
124 ArgVector DstArgs;
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000125 /// Index for the first variadic parameter if exist.
126 unsigned VariadicIndex;
127 /// Show when a function has variadic parameters. If it has, it marks all
128 /// of them as source or destination.
129 VariadicType VarType;
Anna Zaks3666d2c2012-01-17 00:37:02 +0000130
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000131 TaintPropagationRule()
132 : VariadicIndex(InvalidArgIndex), VarType(VariadicType::None) {}
Anna Zaks3666d2c2012-01-17 00:37:02 +0000133
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000134 TaintPropagationRule(std::initializer_list<unsigned> &&Src,
135 std::initializer_list<unsigned> &&Dst,
136 VariadicType Var = VariadicType::None,
137 unsigned VarIndex = InvalidArgIndex)
138 : SrcArgs(std::move(Src)), DstArgs(std::move(Dst)),
139 VariadicIndex(VarIndex), VarType(Var) {}
Anna Zaks5d324e52012-01-18 02:45:07 +0000140
141 /// Get the propagation rule for a given function.
142 static TaintPropagationRule
Artem Dergachevb68cb542018-12-19 23:35:08 +0000143 getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
144 CheckerContext &C);
Anna Zaks5d324e52012-01-18 02:45:07 +0000145
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000146 void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
147 void addDstArg(unsigned A) { DstArgs.push_back(A); }
Anna Zaks3666d2c2012-01-17 00:37:02 +0000148
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000149 bool isNull() const {
150 return SrcArgs.empty() && DstArgs.empty() &&
151 VariadicType::None == VarType;
Anna Zaks5d324e52012-01-18 02:45:07 +0000152 }
Anna Zaks3666d2c2012-01-17 00:37:02 +0000153
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000154 bool isDestinationArgument(unsigned ArgNum) const {
155 return (llvm::find(DstArgs, ArgNum) != DstArgs.end());
156 }
157
158 static bool isTaintedOrPointsToTainted(const Expr *E, ProgramStateRef State,
159 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 "
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000190 "for character data and the null terminator)";
Anna Zaks560dbe92012-01-18 02:45:11 +0000191
192} // end of anonymous namespace
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000193
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000194/// A set which is used to pass information from call pre-visit instruction
195/// to the call post-visit. The values are unsigned integers, which are either
196/// ReturnValueIndex, or indexes of the pointer/reference argument, which
197/// points to data, which should be tainted on return.
Jordan Rose0c153cb2012-11-02 01:54:06 +0000198REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned)
Anna Zaks3b0ab202011-12-17 00:26:34 +0000199
Anna Zaks5d324e52012-01-18 02:45:07 +0000200GenericTaintChecker::TaintPropagationRule
201GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
Artem Dergachevb68cb542018-12-19 23:35:08 +0000202 const FunctionDecl *FDecl, StringRef Name, CheckerContext &C) {
Enrico Pertoso4432d872015-06-03 09:10:58 +0000203 // TODO: Currently, we might lose precision here: we always mark a return
Anna Zaksbf740512012-01-24 19:32:25 +0000204 // value as tainted even if it's just a pointer, pointing to tainted data.
205
Anna Zaks5d324e52012-01-18 02:45:07 +0000206 // Check for exact name match for functions without builtin substitutes.
Artem Dergachevb68cb542018-12-19 23:35:08 +0000207 TaintPropagationRule Rule =
208 llvm::StringSwitch<TaintPropagationRule>(Name)
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000209 .Case("atoi", TaintPropagationRule({0}, {ReturnValueIndex}))
210 .Case("atol", TaintPropagationRule({0}, {ReturnValueIndex}))
211 .Case("atoll", TaintPropagationRule({0}, {ReturnValueIndex}))
212 .Case("getc", TaintPropagationRule({0}, {ReturnValueIndex}))
213 .Case("fgetc", TaintPropagationRule({0}, {ReturnValueIndex}))
214 .Case("getc_unlocked", TaintPropagationRule({0}, {ReturnValueIndex}))
215 .Case("getw", TaintPropagationRule({0}, {ReturnValueIndex}))
216 .Case("toupper", TaintPropagationRule({0}, {ReturnValueIndex}))
217 .Case("tolower", TaintPropagationRule({0}, {ReturnValueIndex}))
218 .Case("strchr", TaintPropagationRule({0}, {ReturnValueIndex}))
219 .Case("strrchr", TaintPropagationRule({0}, {ReturnValueIndex}))
220 .Case("read", TaintPropagationRule({0, 2}, {1, ReturnValueIndex}))
221 .Case("pread",
222 TaintPropagationRule({0, 1, 2, 3}, {1, ReturnValueIndex}))
223 .Case("gets", TaintPropagationRule({}, {0, ReturnValueIndex}))
224 .Case("fgets", TaintPropagationRule({2}, {0, ReturnValueIndex}))
225 .Case("getline", TaintPropagationRule({2}, {0}))
226 .Case("getdelim", TaintPropagationRule({3}, {0}))
227 .Case("fgetln", TaintPropagationRule({0}, {ReturnValueIndex}))
Artem Dergachevb68cb542018-12-19 23:35:08 +0000228 .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:
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000242 return TaintPropagationRule({1, 2}, {0, ReturnValueIndex});
Anna Zaks5d324e52012-01-18 02:45:07 +0000243 case Builtin::BIstrlcpy:
244 case Builtin::BIstrlcat:
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000245 return TaintPropagationRule({1, 2}, {0});
Anna Zaks5d324e52012-01-18 02:45:07 +0000246 case Builtin::BIstrndup:
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000247 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()) {
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000255 if (C.isCLibraryFunction(FDecl, "snprintf"))
256 return TaintPropagationRule({1}, {0, ReturnValueIndex}, VariadicType::Src,
257 3);
258 else if (C.isCLibraryFunction(FDecl, "sprintf"))
259 return TaintPropagationRule({}, {0, ReturnValueIndex}, VariadicType::Src,
260 2);
Anna Zaks5d324e52012-01-18 02:45:07 +0000261 else if (C.isCLibraryFunction(FDecl, "strcpy") ||
262 C.isCLibraryFunction(FDecl, "stpcpy") ||
263 C.isCLibraryFunction(FDecl, "strcat"))
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000264 return TaintPropagationRule({1}, {0, ReturnValueIndex});
Anna Zaks5d324e52012-01-18 02:45:07 +0000265 else if (C.isCLibraryFunction(FDecl, "bcopy"))
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000266 return TaintPropagationRule({0, 2}, {1});
Anna Zaks5d324e52012-01-18 02:45:07 +0000267 else if (C.isCLibraryFunction(FDecl, "strdup") ||
268 C.isCLibraryFunction(FDecl, "strdupa"))
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000269 return TaintPropagationRule({0}, {ReturnValueIndex});
Anna Zaks560dbe92012-01-18 02:45:11 +0000270 else if (C.isCLibraryFunction(FDecl, "wcsdup"))
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000271 return TaintPropagationRule({0}, {ReturnValueIndex});
Anna Zaks5d324e52012-01-18 02:45:07 +0000272 }
273
274 // Skipping the following functions, since they might be used for cleansing
275 // or smart memory copy:
Benjamin Kramer474261a2012-06-02 10:20:41 +0000276 // - memccpy - copying until hitting a special character.
Anna Zaks5d324e52012-01-18 02:45:07 +0000277
278 return TaintPropagationRule();
Anna Zaks457c6872011-11-18 02:26:36 +0000279}
280
Anna Zaks3b0ab202011-12-17 00:26:34 +0000281void GenericTaintChecker::checkPreStmt(const CallExpr *CE,
282 CheckerContext &C) const {
Anna Zaks126a2ef2012-01-07 02:33:10 +0000283 // Check for errors first.
284 if (checkPre(CE, C))
285 return;
Anna Zaks3b0ab202011-12-17 00:26:34 +0000286
Anna Zaks126a2ef2012-01-07 02:33:10 +0000287 // Add taint second.
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000288 addSourcesPre(CE, C);
Anna Zaks126a2ef2012-01-07 02:33:10 +0000289}
290
291void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
292 CheckerContext &C) const {
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000293 if (propagateFromPre(CE, C))
294 return;
295 addSourcesPost(CE, C);
Anna Zaks126a2ef2012-01-07 02:33:10 +0000296}
297
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000298void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
299 CheckerContext &C) const {
Craig Topper0dbb7832014-05-27 02:45:47 +0000300 ProgramStateRef State = nullptr;
Anna Zaks5d324e52012-01-18 02:45:07 +0000301 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
Jordan Rose6cd16c52012-07-10 23:13:01 +0000302 if (!FDecl || FDecl->getKind() != Decl::Function)
303 return;
304
Anna Zaks5d324e52012-01-18 02:45:07 +0000305 StringRef Name = C.getCalleeName(FDecl);
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000306 if (Name.empty())
307 return;
Anna Zaks3666d2c2012-01-17 00:37:02 +0000308
Anna Zaks5d324e52012-01-18 02:45:07 +0000309 // First, try generating a propagation rule for this function.
310 TaintPropagationRule Rule =
Artem Dergachevb68cb542018-12-19 23:35:08 +0000311 TaintPropagationRule::getTaintPropagationRule(FDecl, Name, C);
Anna Zaks3666d2c2012-01-17 00:37:02 +0000312 if (!Rule.isNull()) {
Anna Zaks7f6a6b72012-01-18 02:45:13 +0000313 State = Rule.process(CE, C);
Anna Zaks3666d2c2012-01-17 00:37:02 +0000314 if (!State)
315 return;
316 C.addTransition(State);
Anna Zaks5d324e52012-01-18 02:45:07 +0000317 return;
Anna Zaks3666d2c2012-01-17 00:37:02 +0000318 }
319
Anna Zaks5d324e52012-01-18 02:45:07 +0000320 // Otherwise, check if we have custom pre-processing implemented.
Anna Zaks3b0ab202011-12-17 00:26:34 +0000321 FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
Artem Dergachevb68cb542018-12-19 23:35:08 +0000322 .Case("fscanf", &GenericTaintChecker::preFscanf)
323 .Default(nullptr);
Anna Zaks3b0ab202011-12-17 00:26:34 +0000324 // Check and evaluate the call.
325 if (evalFunction)
326 State = (this->*evalFunction)(CE, C);
327 if (!State)
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000328 return;
Anna Zaks3b0ab202011-12-17 00:26:34 +0000329 C.addTransition(State);
330}
331
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000332bool GenericTaintChecker::propagateFromPre(const CallExpr *CE,
333 CheckerContext &C) const {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000334 ProgramStateRef State = C.getState();
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000335
336 // Depending on what was tainted at pre-visit, we determined a set of
337 // arguments which should be tainted after the function returns. These are
338 // stored in the state as TaintArgsOnPostVisit set.
Jordan Rose0c153cb2012-11-02 01:54:06 +0000339 TaintArgsOnPostVisitTy TaintArgs = State->get<TaintArgsOnPostVisit>();
Anna Zaksbf740512012-01-24 19:32:25 +0000340 if (TaintArgs.isEmpty())
341 return false;
342
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000343 for (unsigned ArgNum : TaintArgs) {
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000344 // Special handling for the tainted return value.
345 if (ArgNum == ReturnValueIndex) {
346 State = State->addTaint(CE, C.getLocationContext());
347 continue;
348 }
349
350 // The arguments are pointer arguments. The data they are pointing at is
351 // tainted after the call.
Anna Zaksb508d292012-04-10 23:41:11 +0000352 if (CE->getNumArgs() < (ArgNum + 1))
353 return false;
Artem Dergachevb68cb542018-12-19 23:35:08 +0000354 const Expr *Arg = CE->getArg(ArgNum);
Artem Dergacheveed7a312017-05-29 15:42:56 +0000355 Optional<SVal> V = getPointedToSVal(C, Arg);
356 if (V)
357 State = State->addTaint(*V);
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000358 }
359
360 // Clear up the taint info from the state.
361 State = State->remove<TaintArgsOnPostVisit>();
362
363 if (State != C.getState()) {
364 C.addTransition(State);
365 return true;
366 }
367 return false;
368}
369
370void GenericTaintChecker::addSourcesPost(const CallExpr *CE,
371 CheckerContext &C) const {
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000372 // Define the attack surface.
373 // Set the evaluation function by switching on the callee name.
Jordan Rose6cd16c52012-07-10 23:13:01 +0000374 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
375 if (!FDecl || FDecl->getKind() != Decl::Function)
376 return;
377
378 StringRef Name = C.getCalleeName(FDecl);
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000379 if (Name.empty())
380 return;
Artem Dergachevb68cb542018-12-19 23:35:08 +0000381 FnCheck evalFunction =
382 llvm::StringSwitch<FnCheck>(Name)
383 .Case("scanf", &GenericTaintChecker::postScanf)
384 // TODO: Add support for vfscanf & family.
385 .Case("getchar", &GenericTaintChecker::postRetTaint)
386 .Case("getchar_unlocked", &GenericTaintChecker::postRetTaint)
387 .Case("getenv", &GenericTaintChecker::postRetTaint)
388 .Case("fopen", &GenericTaintChecker::postRetTaint)
389 .Case("fdopen", &GenericTaintChecker::postRetTaint)
390 .Case("freopen", &GenericTaintChecker::postRetTaint)
391 .Case("getch", &GenericTaintChecker::postRetTaint)
392 .Case("wgetch", &GenericTaintChecker::postRetTaint)
393 .Case("socket", &GenericTaintChecker::postSocket)
394 .Default(nullptr);
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000395
396 // If the callee isn't defined, it is not of security concern.
397 // Check and evaluate the call.
Craig Topper0dbb7832014-05-27 02:45:47 +0000398 ProgramStateRef State = nullptr;
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000399 if (evalFunction)
Anna Zaks3b0ab202011-12-17 00:26:34 +0000400 State = (this->*evalFunction)(CE, C);
401 if (!State)
402 return;
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000403
Anna Zaks3b0ab202011-12-17 00:26:34 +0000404 C.addTransition(State);
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000405}
Anna Zaks457c6872011-11-18 02:26:36 +0000406
Artem Dergachevb68cb542018-12-19 23:35:08 +0000407bool GenericTaintChecker::checkPre(const CallExpr *CE,
408 CheckerContext &C) const {
Anna Zaks126a2ef2012-01-07 02:33:10 +0000409
410 if (checkUncontrolledFormatString(CE, C))
411 return true;
412
Anna Zaks560dbe92012-01-18 02:45:11 +0000413 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
Jordan Rose6cd16c52012-07-10 23:13:01 +0000414 if (!FDecl || FDecl->getKind() != Decl::Function)
415 return false;
416
Anna Zaks560dbe92012-01-18 02:45:11 +0000417 StringRef Name = C.getCalleeName(FDecl);
Anna Zaks0244cd72012-01-14 02:48:40 +0000418 if (Name.empty())
419 return false;
420
421 if (checkSystemCall(CE, Name, C))
422 return true;
423
Anna Zaks560dbe92012-01-18 02:45:11 +0000424 if (checkTaintedBufferSize(CE, FDecl, C))
425 return true;
426
Anna Zaks126a2ef2012-01-07 02:33:10 +0000427 return false;
428}
429
Artem Dergacheveed7a312017-05-29 15:42:56 +0000430Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
Artem Dergachev3ef5deb2017-12-12 02:27:55 +0000431 const Expr *Arg) {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000432 ProgramStateRef State = C.getState();
George Karpenkovd703ec92018-01-17 20:27:29 +0000433 SVal AddrVal = C.getSVal(Arg->IgnoreParens());
Anna Zakse48ee502011-12-16 18:28:50 +0000434 if (AddrVal.isUnknownOrUndef())
Artem Dergacheveed7a312017-05-29 15:42:56 +0000435 return None;
Anna Zaks7c96b7d2011-12-11 18:43:40 +0000436
David Blaikie05785d12013-02-20 22:23:23 +0000437 Optional<Loc> AddrLoc = AddrVal.getAs<Loc>();
Anna Zaks7f6a6b72012-01-18 02:45:13 +0000438 if (!AddrLoc)
Artem Dergacheveed7a312017-05-29 15:42:56 +0000439 return None;
Anna Zaks457c6872011-11-18 02:26:36 +0000440
Artem Dergachev3ef5deb2017-12-12 02:27:55 +0000441 QualType ArgTy = Arg->getType().getCanonicalType();
442 if (!ArgTy->isPointerType())
443 return None;
444
445 QualType ValTy = ArgTy->getPointeeType();
446
447 // Do not dereference void pointers. Treat them as byte pointers instead.
448 // FIXME: we might want to consider more than just the first byte.
449 if (ValTy->isVoidType())
450 ValTy = C.getASTContext().CharTy;
451
452 return State->getSVal(*AddrLoc, ValTy);
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000453}
454
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000455ProgramStateRef
Anna Zaks7f6a6b72012-01-18 02:45:13 +0000456GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
457 CheckerContext &C) const {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000458 ProgramStateRef State = C.getState();
Anna Zaks3666d2c2012-01-17 00:37:02 +0000459
460 // Check for taint in arguments.
Kristof Umann85547832019-03-05 12:42:59 +0000461 bool IsTainted = true;
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000462 for (unsigned ArgNum : SrcArgs) {
463 if (ArgNum >= CE->getNumArgs())
Anna Zaksb508d292012-04-10 23:41:11 +0000464 return State;
Anna Zaksbf740512012-01-24 19:32:25 +0000465 if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(ArgNum), State, C)))
Anna Zaks3666d2c2012-01-17 00:37:02 +0000466 break;
467 }
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000468
469 // Check for taint in variadic arguments.
470 if (!IsTainted && VariadicType::Src == VarType) {
471 // Check if any of the arguments is tainted
472 for (unsigned int i = VariadicIndex; i < CE->getNumArgs(); ++i) {
473 if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(i), State, C)))
474 break;
475 }
476 }
477
Anna Zaks3666d2c2012-01-17 00:37:02 +0000478 if (!IsTainted)
479 return State;
480
481 // Mark the arguments which should be tainted after the function returns.
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000482 for (unsigned ArgNum : DstArgs) {
Anna Zaks3666d2c2012-01-17 00:37:02 +0000483 // Should mark the return value?
484 if (ArgNum == ReturnValueIndex) {
485 State = State->add<TaintArgsOnPostVisit>(ReturnValueIndex);
486 continue;
487 }
488
489 // Mark the given argument.
490 assert(ArgNum < CE->getNumArgs());
491 State = State->add<TaintArgsOnPostVisit>(ArgNum);
492 }
493
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000494 // Mark all variadic arguments tainted if present.
495 if (VariadicType::Dst == VarType) {
496 // For all pointer and references that were passed in:
497 // If they are not pointing to const data, mark data as tainted.
498 // TODO: So far we are just going one level down; ideally we'd need to
499 // recurse here.
500 for (unsigned int i = VariadicIndex; i < CE->getNumArgs(); ++i) {
501 const Expr *Arg = CE->getArg(i);
502 // Process pointer argument.
503 const Type *ArgTy = Arg->getType().getTypePtr();
504 QualType PType = ArgTy->getPointeeType();
505 if ((!PType.isNull() && !PType.isConstQualified()) ||
506 (ArgTy->isReferenceType() && !Arg->getType().isConstQualified()))
507 State = State->add<TaintArgsOnPostVisit>(i);
508 }
509 }
510
Anna Zaks3666d2c2012-01-17 00:37:02 +0000511 return State;
512}
513
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000514// If argument 0 (file descriptor) is tainted, all arguments except for arg 0
515// and arg 1 should get taint.
Ted Kremenek49b1e382012-01-26 21:29:00 +0000516ProgramStateRef GenericTaintChecker::preFscanf(const CallExpr *CE,
Artem Dergachevb68cb542018-12-19 23:35:08 +0000517 CheckerContext &C) const {
Anna Zaks3b0ab202011-12-17 00:26:34 +0000518 assert(CE->getNumArgs() >= 2);
Ted Kremenek49b1e382012-01-26 21:29:00 +0000519 ProgramStateRef State = C.getState();
Anna Zaks3b0ab202011-12-17 00:26:34 +0000520
521 // Check is the file descriptor is tainted.
Ted Kremenek632e3b72012-01-06 22:09:28 +0000522 if (State->isTainted(CE->getArg(0), C.getLocationContext()) ||
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000523 isStdin(CE->getArg(0), C)) {
524 // All arguments except for the first two should get taint.
525 for (unsigned int i = 2; i < CE->getNumArgs(); ++i)
Artem Dergachevb68cb542018-12-19 23:35:08 +0000526 State = State->add<TaintArgsOnPostVisit>(i);
Anna Zaksb3fa8d72012-01-12 02:22:34 +0000527 return State;
528 }
529
Craig Topper0dbb7832014-05-27 02:45:47 +0000530 return nullptr;
Anna Zaks3b0ab202011-12-17 00:26:34 +0000531}
532
Anna Zaks3b754b22012-01-20 00:11:19 +0000533// If argument 0(protocol domain) is network, the return value should get taint.
Ted Kremenek49b1e382012-01-26 21:29:00 +0000534ProgramStateRef GenericTaintChecker::postSocket(const CallExpr *CE,
Anna Zaksb508d292012-04-10 23:41:11 +0000535 CheckerContext &C) const {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000536 ProgramStateRef State = C.getState();
Anna Zaksb508d292012-04-10 23:41:11 +0000537 if (CE->getNumArgs() < 3)
538 return State;
Anna Zaks3b754b22012-01-20 00:11:19 +0000539
540 SourceLocation DomLoc = CE->getArg(0)->getExprLoc();
541 StringRef DomName = C.getMacroNameOrSpelling(DomLoc);
542 // White list the internal communication protocols.
543 if (DomName.equals("AF_SYSTEM") || DomName.equals("AF_LOCAL") ||
544 DomName.equals("AF_UNIX") || DomName.equals("AF_RESERVED_36"))
545 return State;
546 State = State->addTaint(CE, C.getLocationContext());
547 return State;
548}
549
Ted Kremenek49b1e382012-01-26 21:29:00 +0000550ProgramStateRef GenericTaintChecker::postScanf(const CallExpr *CE,
Artem Dergachevb68cb542018-12-19 23:35:08 +0000551 CheckerContext &C) const {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000552 ProgramStateRef State = C.getState();
Anna Zaksb508d292012-04-10 23:41:11 +0000553 if (CE->getNumArgs() < 2)
554 return State;
555
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000556 // All arguments except for the very first one should get taint.
557 for (unsigned int i = 1; i < CE->getNumArgs(); ++i) {
558 // The arguments are pointer arguments. The data they are pointing at is
559 // tainted after the call.
Artem Dergachevb68cb542018-12-19 23:35:08 +0000560 const Expr *Arg = CE->getArg(i);
Artem Dergacheveed7a312017-05-29 15:42:56 +0000561 Optional<SVal> V = getPointedToSVal(C, Arg);
562 if (V)
563 State = State->addTaint(*V);
Anna Zakseefc0e92011-12-14 00:56:02 +0000564 }
Anna Zaks3b0ab202011-12-17 00:26:34 +0000565 return State;
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000566}
567
Ted Kremenek49b1e382012-01-26 21:29:00 +0000568ProgramStateRef GenericTaintChecker::postRetTaint(const CallExpr *CE,
Anna Zaksb508d292012-04-10 23:41:11 +0000569 CheckerContext &C) const {
Ted Kremenek632e3b72012-01-06 22:09:28 +0000570 return C.getState()->addTaint(CE, C.getLocationContext());
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000571}
572
Anna Zaksbf740512012-01-24 19:32:25 +0000573bool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) {
Ted Kremenek49b1e382012-01-26 21:29:00 +0000574 ProgramStateRef State = C.getState();
George Karpenkovd703ec92018-01-17 20:27:29 +0000575 SVal Val = C.getSVal(E);
Anna Zaks099fe3f2011-12-14 00:56:18 +0000576
Anna Zakse48ee502011-12-16 18:28:50 +0000577 // stdin is a pointer, so it would be a region.
578 const MemRegion *MemReg = Val.getAsRegion();
579
580 // The region should be symbolic, we do not know it's value.
581 const SymbolicRegion *SymReg = dyn_cast_or_null<SymbolicRegion>(MemReg);
582 if (!SymReg)
Anna Zaks099fe3f2011-12-14 00:56:18 +0000583 return false;
584
Anna Zakse48ee502011-12-16 18:28:50 +0000585 // Get it's symbol and find the declaration region it's pointing to.
Artem Dergachevb68cb542018-12-19 23:35:08 +0000586 const SymbolRegionValue *Sm =
587 dyn_cast<SymbolRegionValue>(SymReg->getSymbol());
Anna Zakse48ee502011-12-16 18:28:50 +0000588 if (!Sm)
589 return false;
590 const DeclRegion *DeclReg = dyn_cast_or_null<DeclRegion>(Sm->getRegion());
591 if (!DeclReg)
592 return false;
Anna Zaks099fe3f2011-12-14 00:56:18 +0000593
Anna Zakse48ee502011-12-16 18:28:50 +0000594 // This region corresponds to a declaration, find out if it's a global/extern
595 // variable named stdin with the proper type.
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000596 if (const auto *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) {
Anna Zakse48ee502011-12-16 18:28:50 +0000597 D = D->getCanonicalDecl();
Artem Dergachev2a5fb122019-01-30 00:06:43 +0000598 if ((D->getName().find("stdin") != StringRef::npos) && D->isExternC()) {
599 const auto *PtrTy = dyn_cast<PointerType>(D->getType().getTypePtr());
600 if (PtrTy && PtrTy->getPointeeType().getCanonicalType() ==
601 C.getASTContext().getFILEType().getCanonicalType())
602 return true;
603 }
Anna Zakse48ee502011-12-16 18:28:50 +0000604 }
Anna Zaks099fe3f2011-12-14 00:56:18 +0000605 return false;
606}
607
Anna Zaks126a2ef2012-01-07 02:33:10 +0000608static bool getPrintfFormatArgumentNum(const CallExpr *CE,
609 const CheckerContext &C,
610 unsigned int &ArgNum) {
611 // Find if the function contains a format string argument.
612 // Handles: fprintf, printf, sprintf, snprintf, vfprintf, vprintf, vsprintf,
613 // vsnprintf, syslog, custom annotated functions.
614 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
615 if (!FDecl)
616 return false;
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +0000617 for (const auto *Format : FDecl->specific_attrs<FormatAttr>()) {
Anna Zaks126a2ef2012-01-07 02:33:10 +0000618 ArgNum = Format->getFormatIdx() - 1;
Artem Dergachevb68cb542018-12-19 23:35:08 +0000619 if ((Format->getType()->getName() == "printf") && CE->getNumArgs() > ArgNum)
Anna Zaks126a2ef2012-01-07 02:33:10 +0000620 return true;
621 }
622
623 // Or if a function is named setproctitle (this is a heuristic).
624 if (C.getCalleeName(CE).find("setproctitle") != StringRef::npos) {
625 ArgNum = 0;
626 return true;
627 }
628
629 return false;
630}
631
Anna Zaks0244cd72012-01-14 02:48:40 +0000632bool GenericTaintChecker::generateReportIfTainted(const Expr *E,
633 const char Msg[],
634 CheckerContext &C) const {
635 assert(E);
636
637 // Check for taint.
Ted Kremenek49b1e382012-01-26 21:29:00 +0000638 ProgramStateRef State = C.getState();
Artem Dergacheveed7a312017-05-29 15:42:56 +0000639 Optional<SVal> PointedToSVal = getPointedToSVal(C, E);
Anna Zaksd4e43ae2017-03-09 00:01:07 +0000640 SVal TaintedSVal;
Artem Dergacheveed7a312017-05-29 15:42:56 +0000641 if (PointedToSVal && State->isTainted(*PointedToSVal))
642 TaintedSVal = *PointedToSVal;
Anna Zaksd4e43ae2017-03-09 00:01:07 +0000643 else if (State->isTainted(E, C.getLocationContext()))
644 TaintedSVal = C.getSVal(E);
645 else
Anna Zaks0244cd72012-01-14 02:48:40 +0000646 return false;
647
648 // Generate diagnostic.
Devin Coughline39bd402015-09-16 22:03:05 +0000649 if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
Anna Zaks0244cd72012-01-14 02:48:40 +0000650 initBugType();
Aaron Ballman8d3a7a52015-06-23 13:15:32 +0000651 auto report = llvm::make_unique<BugReport>(*BT, Msg, N);
Anna Zaks0244cd72012-01-14 02:48:40 +0000652 report->addRange(E->getSourceRange());
Anna Zaksd4e43ae2017-03-09 00:01:07 +0000653 report->addVisitor(llvm::make_unique<TaintBugVisitor>(TaintedSVal));
Aaron Ballman8d3a7a52015-06-23 13:15:32 +0000654 C.emitReport(std::move(report));
Anna Zaks0244cd72012-01-14 02:48:40 +0000655 return true;
656 }
657 return false;
658}
659
Artem Dergachevb68cb542018-12-19 23:35:08 +0000660bool GenericTaintChecker::checkUncontrolledFormatString(
661 const CallExpr *CE, CheckerContext &C) const {
Anna Zaks126a2ef2012-01-07 02:33:10 +0000662 // Check if the function contains a format string argument.
663 unsigned int ArgNum = 0;
664 if (!getPrintfFormatArgumentNum(CE, C, ArgNum))
665 return false;
666
Artem Dergachevb68cb542018-12-19 23:35:08 +0000667 // If either the format string content or the pointer itself are tainted,
668 // warn.
Alexander Kornienko9c104902015-12-28 13:06:58 +0000669 return generateReportIfTainted(CE->getArg(ArgNum),
670 MsgUncontrolledFormatString, C);
Anna Zaks0244cd72012-01-14 02:48:40 +0000671}
672
Artem Dergachevb68cb542018-12-19 23:35:08 +0000673bool GenericTaintChecker::checkSystemCall(const CallExpr *CE, StringRef Name,
Anna Zaks0244cd72012-01-14 02:48:40 +0000674 CheckerContext &C) const {
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000675 // TODO: It might make sense to run this check on demand. In some cases,
676 // we should check if the environment has been cleansed here. We also might
Anna Zaksbf740512012-01-24 19:32:25 +0000677 // need to know if the user was reset before these calls(seteuid).
Anna Zaks0244cd72012-01-14 02:48:40 +0000678 unsigned ArgNum = llvm::StringSwitch<unsigned>(Name)
Artem Dergachevb68cb542018-12-19 23:35:08 +0000679 .Case("system", 0)
680 .Case("popen", 0)
681 .Case("execl", 0)
682 .Case("execle", 0)
683 .Case("execlp", 0)
684 .Case("execv", 0)
685 .Case("execvp", 0)
686 .Case("execvP", 0)
687 .Case("execve", 0)
688 .Case("dlopen", 0)
689 .Default(UINT_MAX);
Anna Zaks0244cd72012-01-14 02:48:40 +0000690
Anna Zaksb508d292012-04-10 23:41:11 +0000691 if (ArgNum == UINT_MAX || CE->getNumArgs() < (ArgNum + 1))
Anna Zaks0244cd72012-01-14 02:48:40 +0000692 return false;
693
Alexander Kornienko9c104902015-12-28 13:06:58 +0000694 return generateReportIfTainted(CE->getArg(ArgNum), MsgSanitizeSystemArgs, C);
Anna Zaks126a2ef2012-01-07 02:33:10 +0000695}
696
Anna Zaks560dbe92012-01-18 02:45:11 +0000697// TODO: Should this check be a part of the CString checker?
698// If yes, should taint be a global setting?
699bool GenericTaintChecker::checkTaintedBufferSize(const CallExpr *CE,
700 const FunctionDecl *FDecl,
701 CheckerContext &C) const {
702 // If the function has a buffer size argument, set ArgNum.
703 unsigned ArgNum = InvalidArgIndex;
704 unsigned BId = 0;
Artem Dergachevb68cb542018-12-19 23:35:08 +0000705 if ((BId = FDecl->getMemoryFunctionKind()))
706 switch (BId) {
Anna Zaks560dbe92012-01-18 02:45:11 +0000707 case Builtin::BImemcpy:
708 case Builtin::BImemmove:
709 case Builtin::BIstrncpy:
710 ArgNum = 2;
711 break;
712 case Builtin::BIstrndup:
713 ArgNum = 1;
714 break;
715 default:
716 break;
717 };
718
719 if (ArgNum == InvalidArgIndex) {
720 if (C.isCLibraryFunction(FDecl, "malloc") ||
721 C.isCLibraryFunction(FDecl, "calloc") ||
722 C.isCLibraryFunction(FDecl, "alloca"))
723 ArgNum = 0;
724 else if (C.isCLibraryFunction(FDecl, "memccpy"))
725 ArgNum = 3;
726 else if (C.isCLibraryFunction(FDecl, "realloc"))
727 ArgNum = 1;
728 else if (C.isCLibraryFunction(FDecl, "bcopy"))
729 ArgNum = 2;
730 }
731
Alexander Kornienko9c104902015-12-28 13:06:58 +0000732 return ArgNum != InvalidArgIndex && CE->getNumArgs() > ArgNum &&
733 generateReportIfTainted(CE->getArg(ArgNum), MsgTaintedBufferSize, C);
Anna Zaks560dbe92012-01-18 02:45:11 +0000734}
735
Anna Zaks5c5bf9b2011-11-16 19:58:13 +0000736void ento::registerGenericTaintChecker(CheckerManager &mgr) {
737 mgr.registerChecker<GenericTaintChecker>();
738}
Kristof Umann058a7a42019-01-26 14:23:08 +0000739
740bool ento::shouldRegisterGenericTaintChecker(const LangOptions &LO) {
741 return true;
742}