blob: 62b54933dd6b7424c1b4983db7897e327d69e119 [file] [log] [blame]
Anna Zaksdf18c5a2011-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//===----------------------------------------------------------------------===//
17#include "ClangSACheckers.h"
18#include "clang/StaticAnalyzer/Core/Checker.h"
19#include "clang/StaticAnalyzer/Core/CheckerManager.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
Anna Zaks9ffbe242011-12-17 00:26:34 +000021#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
Anna Zaksdf18c5a2011-11-16 19:58:13 +000022#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
Anna Zaks1fb826a2012-01-12 02:22:34 +000023#include <climits>
Anna Zaksdf18c5a2011-11-16 19:58:13 +000024
25using namespace clang;
26using namespace ento;
27
28namespace {
Anna Zaksefd69892011-12-14 00:56:18 +000029class GenericTaintChecker : public Checker< check::PostStmt<CallExpr>,
Anna Zaks9ffbe242011-12-17 00:26:34 +000030 check::PreStmt<CallExpr> > {
31public:
Anna Zaks8568ee72012-01-14 02:48:40 +000032 static void *getTag() { static int Tag; return &Tag; }
33
34 void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
35 void checkPostStmt(const DeclRefExpr *DRE, CheckerContext &C) const;
36
37 void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
Anna Zaksdf18c5a2011-11-16 19:58:13 +000038
Anna Zaks9ffbe242011-12-17 00:26:34 +000039private:
Anna Zaks8568ee72012-01-14 02:48:40 +000040 static const unsigned ReturnValueIndex = UINT_MAX;
41
Anna Zaks8f4caf52011-11-18 02:26:36 +000042 mutable llvm::OwningPtr<BugType> BT;
43 void initBugType() const;
44
Anna Zaks1fb826a2012-01-12 02:22:34 +000045 /// \brief Catch taint related bugs. Check if tainted data is passed to a
46 /// system call etc.
Anna Zaks9f03b622012-01-07 02:33:10 +000047 bool checkPre(const CallExpr *CE, CheckerContext &C) const;
48
Anna Zaks1fb826a2012-01-12 02:22:34 +000049 /// \brief Add taint sources on a pre-visit.
50 void addSourcesPre(const CallExpr *CE, CheckerContext &C) const;
51
52 /// \brief Propagate taint generated at pre-visit.
53 bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const;
54
55 /// \brief Add taint sources on a post visit.
56 void addSourcesPost(const CallExpr *CE, CheckerContext &C) const;
57
58 /// \brief Given a pointer argument, get the symbol of the value it contains
Anna Zaks8f4caf52011-11-18 02:26:36 +000059 /// (points to).
60 SymbolRef getPointedToSymbol(CheckerContext &C,
Anna Zaks9ffbe242011-12-17 00:26:34 +000061 const Expr *Arg,
Anna Zaks1fb826a2012-01-12 02:22:34 +000062 bool IssueWarning = false) const;
Anna Zaksdf18c5a2011-11-16 19:58:13 +000063
Anna Zaks9ffbe242011-12-17 00:26:34 +000064 /// Functions defining the attack surface.
65 typedef const ProgramState *(GenericTaintChecker::*FnCheck)(const CallExpr *,
66 CheckerContext &C) const;
67 const ProgramState *postScanf(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks9ffbe242011-12-17 00:26:34 +000068 const ProgramState *postRetTaint(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks9ffbe242011-12-17 00:26:34 +000069
70 /// Taint the scanned input if the file is tainted.
71 const ProgramState *preFscanf(const CallExpr *CE, CheckerContext &C) const;
72 /// Taint if any of the arguments are tainted.
73 const ProgramState *preAnyArgs(const CallExpr *CE, CheckerContext &C) const;
Anna Zaks1fb826a2012-01-12 02:22:34 +000074 const ProgramState *preStrcpy(const CallExpr *CE, CheckerContext &C) const;
Anna Zaksdf18c5a2011-11-16 19:58:13 +000075
Anna Zaksd3d85482011-12-16 18:28:50 +000076 /// Check if the region the expression evaluates to is the standard input,
77 /// and thus, is tainted.
Anna Zaksefd69892011-12-14 00:56:18 +000078 bool isStdin(const Expr *E, CheckerContext &C) const;
Anna Zaksefd69892011-12-14 00:56:18 +000079
Anna Zaks9f03b622012-01-07 02:33:10 +000080 /// Check for CWE-134: Uncontrolled Format String.
Anna Zaks8568ee72012-01-14 02:48:40 +000081 static const char MsgUncontrolledFormatString[];
Anna Zaks9f03b622012-01-07 02:33:10 +000082 bool checkUncontrolledFormatString(const CallExpr *CE,
83 CheckerContext &C) const;
84
Anna Zaks8568ee72012-01-14 02:48:40 +000085 /// Check for:
86 /// CERT/STR02-C. "Sanitize data passed to complex subsystems"
87 /// CWE-78, "Failure to Sanitize Data into an OS Command"
88 static const char MsgSanitizeSystemArgs[];
89 bool checkSystemCall(const CallExpr *CE, StringRef Name,
90 CheckerContext &C) const;
Anna Zaks9ffbe242011-12-17 00:26:34 +000091
Anna Zaks8568ee72012-01-14 02:48:40 +000092 /// Generate a report if the expression is tainted or points to tainted data.
93 bool generateReportIfTainted(const Expr *E, const char Msg[],
94 CheckerContext &C) const;
Anna Zaks9ffbe242011-12-17 00:26:34 +000095
Anna Zaksdf18c5a2011-11-16 19:58:13 +000096};
Anna Zaks8568ee72012-01-14 02:48:40 +000097// TODO: We probably could use TableGen here.
98const char GenericTaintChecker::MsgUncontrolledFormatString[] =
99 "Tainted format string (CWE-134: Uncontrolled Format String)";
100
101const char GenericTaintChecker::MsgSanitizeSystemArgs[] =
102 "Tainted data passed to a system call "
103 "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
104
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000105}
106
Anna Zaks1fb826a2012-01-12 02:22:34 +0000107/// A set which is used to pass information from call pre-visit instruction
108/// to the call post-visit. The values are unsigned integers, which are either
109/// ReturnValueIndex, or indexes of the pointer/reference argument, which
110/// points to data, which should be tainted on return.
111namespace { struct TaintArgsOnPostVisit{}; }
112namespace clang { namespace ento {
113template<> struct ProgramStateTrait<TaintArgsOnPostVisit>
114 : public ProgramStatePartialTrait<llvm::ImmutableSet<unsigned> > {
115 static void *GDMIndex() { return GenericTaintChecker::getTag(); }
116};
117}}
Anna Zaks9ffbe242011-12-17 00:26:34 +0000118
Anna Zaks8f4caf52011-11-18 02:26:36 +0000119inline void GenericTaintChecker::initBugType() const {
120 if (!BT)
Anna Zaks9f03b622012-01-07 02:33:10 +0000121 BT.reset(new BugType("Taint Analysis", "General"));
Anna Zaks8f4caf52011-11-18 02:26:36 +0000122}
123
Anna Zaks9ffbe242011-12-17 00:26:34 +0000124void GenericTaintChecker::checkPreStmt(const CallExpr *CE,
125 CheckerContext &C) const {
Anna Zaks9f03b622012-01-07 02:33:10 +0000126 // Check for errors first.
127 if (checkPre(CE, C))
128 return;
Anna Zaks9ffbe242011-12-17 00:26:34 +0000129
Anna Zaks9f03b622012-01-07 02:33:10 +0000130 // Add taint second.
Anna Zaks1fb826a2012-01-12 02:22:34 +0000131 addSourcesPre(CE, C);
Anna Zaks9f03b622012-01-07 02:33:10 +0000132}
133
134void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
135 CheckerContext &C) const {
Anna Zaks1fb826a2012-01-12 02:22:34 +0000136 if (propagateFromPre(CE, C))
137 return;
138 addSourcesPost(CE, C);
Anna Zaks9f03b622012-01-07 02:33:10 +0000139}
140
Anna Zaks1fb826a2012-01-12 02:22:34 +0000141void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
142 CheckerContext &C) const {
Anna Zaks9ffbe242011-12-17 00:26:34 +0000143 // Set the evaluation function by switching on the callee name.
144 StringRef Name = C.getCalleeName(CE);
Anna Zaks1fb826a2012-01-12 02:22:34 +0000145 if (Name.empty())
146 return;
Anna Zaks9ffbe242011-12-17 00:26:34 +0000147 FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
Anna Zaks9ffbe242011-12-17 00:26:34 +0000148 .Case("atoi", &GenericTaintChecker::preAnyArgs)
149 .Case("atol", &GenericTaintChecker::preAnyArgs)
150 .Case("atoll", &GenericTaintChecker::preAnyArgs)
Anna Zaks1fb826a2012-01-12 02:22:34 +0000151 .Case("fscanf", &GenericTaintChecker::preFscanf)
152 .Cases("strcpy", "__builtin___strcpy_chk",
153 "__inline_strcpy_chk", &GenericTaintChecker::preStrcpy)
154 .Cases("stpcpy", "__builtin___stpcpy_chk", &GenericTaintChecker::preStrcpy)
155 .Cases("strncpy", "__builtin___strncpy_chk", &GenericTaintChecker::preStrcpy)
Anna Zaks9ffbe242011-12-17 00:26:34 +0000156 .Default(0);
157
158 // Check and evaluate the call.
Anna Zaks9f03b622012-01-07 02:33:10 +0000159 const ProgramState *State = 0;
Anna Zaks9ffbe242011-12-17 00:26:34 +0000160 if (evalFunction)
161 State = (this->*evalFunction)(CE, C);
162 if (!State)
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000163 return;
164
Anna Zaks9ffbe242011-12-17 00:26:34 +0000165 C.addTransition(State);
166}
167
Anna Zaks1fb826a2012-01-12 02:22:34 +0000168bool GenericTaintChecker::propagateFromPre(const CallExpr *CE,
169 CheckerContext &C) const {
170 const ProgramState *State = C.getState();
171
172 // Depending on what was tainted at pre-visit, we determined a set of
173 // arguments which should be tainted after the function returns. These are
174 // stored in the state as TaintArgsOnPostVisit set.
175 llvm::ImmutableSet<unsigned> TaintArgs = State->get<TaintArgsOnPostVisit>();
176 for (llvm::ImmutableSet<unsigned>::iterator
177 I = TaintArgs.begin(), E = TaintArgs.end(); I != E; ++I) {
178 unsigned ArgNum = *I;
179
180 // Special handling for the tainted return value.
181 if (ArgNum == ReturnValueIndex) {
182 State = State->addTaint(CE, C.getLocationContext());
183 continue;
184 }
185
186 // The arguments are pointer arguments. The data they are pointing at is
187 // tainted after the call.
188 const Expr* Arg = CE->getArg(ArgNum);
189 SymbolRef Sym = getPointedToSymbol(C, Arg, true);
190 if (Sym)
191 State = State->addTaint(Sym);
192 }
193
194 // Clear up the taint info from the state.
195 State = State->remove<TaintArgsOnPostVisit>();
196
197 if (State != C.getState()) {
198 C.addTransition(State);
199 return true;
200 }
201 return false;
202}
203
204void GenericTaintChecker::addSourcesPost(const CallExpr *CE,
205 CheckerContext &C) const {
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000206 // Define the attack surface.
207 // Set the evaluation function by switching on the callee name.
Anna Zaks9ffbe242011-12-17 00:26:34 +0000208 StringRef Name = C.getCalleeName(CE);
Anna Zaks1fb826a2012-01-12 02:22:34 +0000209 if (Name.empty())
210 return;
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000211 FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
Anna Zaks9ffbe242011-12-17 00:26:34 +0000212 .Case("scanf", &GenericTaintChecker::postScanf)
Anna Zaks1009ac72011-12-14 00:56:02 +0000213 // TODO: Add support for vfscanf & family.
Anna Zaks9ffbe242011-12-17 00:26:34 +0000214 .Case("getchar", &GenericTaintChecker::postRetTaint)
215 .Case("getenv", &GenericTaintChecker::postRetTaint)
216 .Case("fopen", &GenericTaintChecker::postRetTaint)
217 .Case("fdopen", &GenericTaintChecker::postRetTaint)
218 .Case("freopen", &GenericTaintChecker::postRetTaint)
Anna Zaks1fb826a2012-01-12 02:22:34 +0000219 .Default(0);
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000220
221 // If the callee isn't defined, it is not of security concern.
222 // Check and evaluate the call.
Anna Zaks9f03b622012-01-07 02:33:10 +0000223 const ProgramState *State = 0;
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000224 if (evalFunction)
Anna Zaks9ffbe242011-12-17 00:26:34 +0000225 State = (this->*evalFunction)(CE, C);
226 if (!State)
227 return;
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000228
Anna Zaks9ffbe242011-12-17 00:26:34 +0000229 C.addTransition(State);
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000230}
Anna Zaks8f4caf52011-11-18 02:26:36 +0000231
Anna Zaks9f03b622012-01-07 02:33:10 +0000232bool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{
233
234 if (checkUncontrolledFormatString(CE, C))
235 return true;
236
Anna Zaks8568ee72012-01-14 02:48:40 +0000237 StringRef Name = C.getCalleeName(CE);
238 if (Name.empty())
239 return false;
240
241 if (checkSystemCall(CE, Name, C))
242 return true;
243
Anna Zaks9f03b622012-01-07 02:33:10 +0000244 return false;
245}
246
Anna Zaks8f4caf52011-11-18 02:26:36 +0000247SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C,
248 const Expr* Arg,
249 bool IssueWarning) const {
250 const ProgramState *State = C.getState();
Ted Kremenek5eca4822012-01-06 22:09:28 +0000251 SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext());
Anna Zaksd3d85482011-12-16 18:28:50 +0000252 if (AddrVal.isUnknownOrUndef())
Anna Zakse3d250e2011-12-11 18:43:40 +0000253 return 0;
254
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000255 Loc *AddrLoc = dyn_cast<Loc>(&AddrVal);
Anna Zaks8f4caf52011-11-18 02:26:36 +0000256
257 if (!AddrLoc && !IssueWarning)
258 return 0;
259
260 // If the Expr is not a location, issue a warning.
261 if (!AddrLoc) {
262 assert(IssueWarning);
263 if (ExplodedNode *N = C.generateSink(State)) {
264 initBugType();
265 BugReport *report = new BugReport(*BT, "Pointer argument is expected.",N);
266 report->addRange(Arg->getSourceRange());
267 C.EmitReport(report);
268 }
269 return 0;
270 }
271
Anna Zaks71d29092012-01-13 00:56:51 +0000272 const PointerType *ArgTy =
273 dyn_cast<PointerType>(Arg->getType().getCanonicalType().getTypePtr());
274 assert(ArgTy);
275 SVal Val = State->getSVal(*AddrLoc, ArgTy->getPointeeType());
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000276 return Val.getAsSymbol();
277}
278
Anna Zaks1fb826a2012-01-12 02:22:34 +0000279// If argument 0 (file descriptor) is tainted, all arguments except for arg 0
280// and arg 1 should get taint.
Anna Zaks9ffbe242011-12-17 00:26:34 +0000281const ProgramState *GenericTaintChecker::preFscanf(const CallExpr *CE,
282 CheckerContext &C) const {
283 assert(CE->getNumArgs() >= 2);
284 const ProgramState *State = C.getState();
285
286 // Check is the file descriptor is tainted.
Ted Kremenek5eca4822012-01-06 22:09:28 +0000287 if (State->isTainted(CE->getArg(0), C.getLocationContext()) ||
Anna Zaks1fb826a2012-01-12 02:22:34 +0000288 isStdin(CE->getArg(0), C)) {
289 // All arguments except for the first two should get taint.
290 for (unsigned int i = 2; i < CE->getNumArgs(); ++i)
291 State = State->add<TaintArgsOnPostVisit>(i);
292 return State;
293 }
294
Anna Zaks9ffbe242011-12-17 00:26:34 +0000295 return 0;
296}
297
Anna Zaks8568ee72012-01-14 02:48:40 +0000298// If any arguments are tainted, mark the return value as tainted on post-visit.
Anna Zaks9ffbe242011-12-17 00:26:34 +0000299const ProgramState * GenericTaintChecker::preAnyArgs(const CallExpr *CE,
300 CheckerContext &C) const {
301 for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
302 const ProgramState *State = C.getState();
303 const Expr *Arg = CE->getArg(i);
Ted Kremenek5eca4822012-01-06 22:09:28 +0000304 if (State->isTainted(Arg, C.getLocationContext()) ||
305 State->isTainted(getPointedToSymbol(C, Arg)))
Anna Zaks1fb826a2012-01-12 02:22:34 +0000306 return State = State->add<TaintArgsOnPostVisit>(ReturnValueIndex);
Anna Zaks9ffbe242011-12-17 00:26:34 +0000307 }
308 return 0;
309}
310
Anna Zaks1fb826a2012-01-12 02:22:34 +0000311const ProgramState * GenericTaintChecker::preStrcpy(const CallExpr *CE,
312 CheckerContext &C) const {
313 assert(CE->getNumArgs() >= 2);
314 const Expr *FromArg = CE->getArg(1);
Anna Zaks9ffbe242011-12-17 00:26:34 +0000315 const ProgramState *State = C.getState();
Anna Zaks1fb826a2012-01-12 02:22:34 +0000316 if (State->isTainted(FromArg, C.getLocationContext()) ||
317 State->isTainted(getPointedToSymbol(C, FromArg)))
318 return State = State->add<TaintArgsOnPostVisit>(0);
Anna Zaks9ffbe242011-12-17 00:26:34 +0000319 return 0;
320}
321
322const ProgramState *GenericTaintChecker::postScanf(const CallExpr *CE,
323 CheckerContext &C) const {
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000324 const ProgramState *State = C.getState();
Anna Zaks1009ac72011-12-14 00:56:02 +0000325 assert(CE->getNumArgs() >= 2);
Ted Kremenek5eca4822012-01-06 22:09:28 +0000326 SVal x = State->getSVal(CE->getArg(1), C.getLocationContext());
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000327 // All arguments except for the very first one should get taint.
328 for (unsigned int i = 1; i < CE->getNumArgs(); ++i) {
329 // The arguments are pointer arguments. The data they are pointing at is
330 // tainted after the call.
331 const Expr* Arg = CE->getArg(i);
Anna Zaks1fb826a2012-01-12 02:22:34 +0000332 SymbolRef Sym = getPointedToSymbol(C, Arg, true);
Anna Zaks1009ac72011-12-14 00:56:02 +0000333 if (Sym)
334 State = State->addTaint(Sym);
335 }
Anna Zaks9ffbe242011-12-17 00:26:34 +0000336 return State;
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000337}
338
Anna Zaks9ffbe242011-12-17 00:26:34 +0000339const ProgramState *GenericTaintChecker::postRetTaint(const CallExpr *CE,
340 CheckerContext &C) const {
Ted Kremenek5eca4822012-01-06 22:09:28 +0000341 return C.getState()->addTaint(CE, C.getLocationContext());
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000342}
343
Anna Zaksefd69892011-12-14 00:56:18 +0000344bool GenericTaintChecker::isStdin(const Expr *E,
345 CheckerContext &C) const {
Anna Zaksd3d85482011-12-16 18:28:50 +0000346 const ProgramState *State = C.getState();
Ted Kremenek5eca4822012-01-06 22:09:28 +0000347 SVal Val = State->getSVal(E, C.getLocationContext());
Anna Zaksefd69892011-12-14 00:56:18 +0000348
Anna Zaksd3d85482011-12-16 18:28:50 +0000349 // stdin is a pointer, so it would be a region.
350 const MemRegion *MemReg = Val.getAsRegion();
351
352 // The region should be symbolic, we do not know it's value.
353 const SymbolicRegion *SymReg = dyn_cast_or_null<SymbolicRegion>(MemReg);
354 if (!SymReg)
Anna Zaksefd69892011-12-14 00:56:18 +0000355 return false;
356
Anna Zaksd3d85482011-12-16 18:28:50 +0000357 // Get it's symbol and find the declaration region it's pointing to.
358 const SymbolRegionValue *Sm =dyn_cast<SymbolRegionValue>(SymReg->getSymbol());
359 if (!Sm)
360 return false;
361 const DeclRegion *DeclReg = dyn_cast_or_null<DeclRegion>(Sm->getRegion());
362 if (!DeclReg)
363 return false;
Anna Zaksefd69892011-12-14 00:56:18 +0000364
Anna Zaksd3d85482011-12-16 18:28:50 +0000365 // This region corresponds to a declaration, find out if it's a global/extern
366 // variable named stdin with the proper type.
367 if (const VarDecl *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) {
368 D = D->getCanonicalDecl();
369 if ((D->getName().find("stdin") != StringRef::npos) && D->isExternC())
370 if (const PointerType * PtrTy =
371 dyn_cast<PointerType>(D->getType().getTypePtr()))
372 if (PtrTy->getPointeeType() == C.getASTContext().getFILEType())
373 return true;
374 }
Anna Zaksefd69892011-12-14 00:56:18 +0000375 return false;
376}
377
Anna Zaks9f03b622012-01-07 02:33:10 +0000378static bool getPrintfFormatArgumentNum(const CallExpr *CE,
379 const CheckerContext &C,
380 unsigned int &ArgNum) {
381 // Find if the function contains a format string argument.
382 // Handles: fprintf, printf, sprintf, snprintf, vfprintf, vprintf, vsprintf,
383 // vsnprintf, syslog, custom annotated functions.
384 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
385 if (!FDecl)
386 return false;
387 for (specific_attr_iterator<FormatAttr>
388 i = FDecl->specific_attr_begin<FormatAttr>(),
389 e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) {
390
391 const FormatAttr *Format = *i;
392 ArgNum = Format->getFormatIdx() - 1;
393 if ((Format->getType() == "printf") && CE->getNumArgs() > ArgNum)
394 return true;
395 }
396
397 // Or if a function is named setproctitle (this is a heuristic).
398 if (C.getCalleeName(CE).find("setproctitle") != StringRef::npos) {
399 ArgNum = 0;
400 return true;
401 }
402
403 return false;
404}
405
Anna Zaks8568ee72012-01-14 02:48:40 +0000406bool GenericTaintChecker::generateReportIfTainted(const Expr *E,
407 const char Msg[],
408 CheckerContext &C) const {
409 assert(E);
410
411 // Check for taint.
412 const ProgramState *State = C.getState();
413 if (!State->isTainted(getPointedToSymbol(C, E)) &&
414 !State->isTainted(E, C.getLocationContext()))
415 return false;
416
417 // Generate diagnostic.
418 if (ExplodedNode *N = C.addTransition()) {
419 initBugType();
420 BugReport *report = new BugReport(*BT, Msg, N);
421 report->addRange(E->getSourceRange());
422 C.EmitReport(report);
423 return true;
424 }
425 return false;
426}
427
Anna Zaks9f03b622012-01-07 02:33:10 +0000428bool GenericTaintChecker::checkUncontrolledFormatString(const CallExpr *CE,
429 CheckerContext &C) const{
430 // Check if the function contains a format string argument.
431 unsigned int ArgNum = 0;
432 if (!getPrintfFormatArgumentNum(CE, C, ArgNum))
433 return false;
434
435 // If either the format string content or the pointer itself are tainted, warn.
Anna Zaks8568ee72012-01-14 02:48:40 +0000436 if (generateReportIfTainted(CE->getArg(ArgNum),
437 MsgUncontrolledFormatString, C))
438 return true;
439 return false;
440}
441
442bool GenericTaintChecker::checkSystemCall(const CallExpr *CE,
443 StringRef Name,
444 CheckerContext &C) const {
445 unsigned ArgNum = llvm::StringSwitch<unsigned>(Name)
446 .Case("system", 0)
447 .Case("popen", 0)
448 .Default(UINT_MAX);
449
450 if (ArgNum == UINT_MAX)
451 return false;
452
453 if (generateReportIfTainted(CE->getArg(ArgNum),
454 MsgSanitizeSystemArgs, C))
455 return true;
456
Anna Zaks9f03b622012-01-07 02:33:10 +0000457 return false;
458}
459
Anna Zaksdf18c5a2011-11-16 19:58:13 +0000460void ento::registerGenericTaintChecker(CheckerManager &mgr) {
461 mgr.registerChecker<GenericTaintChecker>();
462}