1 //== GenericTaintChecker.cpp ----------------------------------- -*- C++ -*--=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This checker defines the attack surface for generic taint propagation.
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.
16 //===----------------------------------------------------------------------===//
17 #include "ClangSACheckers.h"
18 #include "clang/AST/Attr.h"
19 #include "clang/Basic/Builtins.h"
20 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
21 #include "clang/StaticAnalyzer/Core/Checker.h"
22 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
23 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
24 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
27 using namespace clang;
31 class GenericTaintChecker : public Checker< check::PostStmt<CallExpr>,
32 check::PreStmt<CallExpr> > {
34 static void *getTag() { static int Tag; return &Tag; }
36 void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
38 void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
41 static const unsigned InvalidArgIndex = UINT_MAX;
42 /// Denotes the return vale.
43 static const unsigned ReturnValueIndex = UINT_MAX - 1;
45 mutable std::unique_ptr<BugType> BT;
46 inline void initBugType() const {
48 BT.reset(new BugType(this, "Use of Untrusted Data", "Untrusted Data"));
51 /// \brief Catch taint related bugs. Check if tainted data is passed to a
53 bool checkPre(const CallExpr *CE, CheckerContext &C) const;
55 /// \brief Add taint sources on a pre-visit.
56 void addSourcesPre(const CallExpr *CE, CheckerContext &C) const;
58 /// \brief Propagate taint generated at pre-visit.
59 bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const;
61 /// \brief Add taint sources on a post visit.
62 void addSourcesPost(const CallExpr *CE, CheckerContext &C) const;
64 /// Check if the region the expression evaluates to is the standard input,
65 /// and thus, is tainted.
66 static bool isStdin(const Expr *E, CheckerContext &C);
68 /// \brief Given a pointer argument, return the value it points to.
69 static Optional<SVal> getPointedToSVal(CheckerContext &C, const Expr *Arg);
71 /// Functions defining the attack surface.
72 typedef ProgramStateRef (GenericTaintChecker::*FnCheck)(const CallExpr *,
73 CheckerContext &C) const;
74 ProgramStateRef postScanf(const CallExpr *CE, CheckerContext &C) const;
75 ProgramStateRef postSocket(const CallExpr *CE, CheckerContext &C) const;
76 ProgramStateRef postRetTaint(const CallExpr *CE, CheckerContext &C) const;
78 /// Taint the scanned input if the file is tainted.
79 ProgramStateRef preFscanf(const CallExpr *CE, CheckerContext &C) const;
81 /// Check for CWE-134: Uncontrolled Format String.
82 static const char MsgUncontrolledFormatString[];
83 bool checkUncontrolledFormatString(const CallExpr *CE,
84 CheckerContext &C) const;
87 /// CERT/STR02-C. "Sanitize data passed to complex subsystems"
88 /// CWE-78, "Failure to Sanitize Data into an OS Command"
89 static const char MsgSanitizeSystemArgs[];
90 bool checkSystemCall(const CallExpr *CE, StringRef Name,
91 CheckerContext &C) const;
93 /// Check if tainted data is used as a buffer size ins strn.. functions,
95 static const char MsgTaintedBufferSize[];
96 bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
97 CheckerContext &C) const;
99 /// Generate a report if the expression is tainted or points to tainted data.
100 bool generateReportIfTainted(const Expr *E, const char Msg[],
101 CheckerContext &C) const;
103 /// The bug visitor prints a diagnostic message at the location where a given
104 /// variable was tainted.
105 class TaintBugVisitor
106 : public BugReporterVisitorImpl<TaintBugVisitor> {
111 TaintBugVisitor(const SVal V) : V(V) {}
112 void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(V); }
114 std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
115 const ExplodedNode *PrevN,
116 BugReporterContext &BRC,
117 BugReport &BR) override;
120 typedef SmallVector<unsigned, 2> ArgVector;
122 /// \brief A struct used to specify taint propagation rules for a function.
124 /// If any of the possible taint source arguments is tainted, all of the
125 /// destination arguments should also be tainted. Use InvalidArgIndex in the
126 /// src list to specify that all of the arguments can introduce taint. Use
127 /// InvalidArgIndex in the dst arguments to signify that all the non-const
128 /// pointer and reference arguments might be tainted on return. If
129 /// ReturnValueIndex is added to the dst list, the return value will be
131 struct TaintPropagationRule {
132 /// List of arguments which can be taint sources and should be checked.
134 /// List of arguments which should be tainted on function return.
136 // TODO: Check if using other data structures would be more optimal.
138 TaintPropagationRule() {}
140 TaintPropagationRule(unsigned SArg,
141 unsigned DArg, bool TaintRet = false) {
142 SrcArgs.push_back(SArg);
143 DstArgs.push_back(DArg);
145 DstArgs.push_back(ReturnValueIndex);
148 TaintPropagationRule(unsigned SArg1, unsigned SArg2,
149 unsigned DArg, bool TaintRet = false) {
150 SrcArgs.push_back(SArg1);
151 SrcArgs.push_back(SArg2);
152 DstArgs.push_back(DArg);
154 DstArgs.push_back(ReturnValueIndex);
157 /// Get the propagation rule for a given function.
158 static TaintPropagationRule
159 getTaintPropagationRule(const FunctionDecl *FDecl,
163 inline void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
164 inline void addDstArg(unsigned A) { DstArgs.push_back(A); }
166 inline bool isNull() const { return SrcArgs.empty(); }
168 inline bool isDestinationArgument(unsigned ArgNum) const {
169 return (std::find(DstArgs.begin(),
170 DstArgs.end(), ArgNum) != DstArgs.end());
173 static inline bool isTaintedOrPointsToTainted(const Expr *E,
174 ProgramStateRef State,
176 if (State->isTainted(E, C.getLocationContext()) || isStdin(E, C))
179 if (!E->getType().getTypePtr()->isPointerType())
182 Optional<SVal> V = getPointedToSVal(C, E);
183 return (V && State->isTainted(*V));
186 /// \brief Pre-process a function which propagates taint according to the
188 ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
193 const unsigned GenericTaintChecker::ReturnValueIndex;
194 const unsigned GenericTaintChecker::InvalidArgIndex;
196 const char GenericTaintChecker::MsgUncontrolledFormatString[] =
197 "Untrusted data is used as a format string "
198 "(CWE-134: Uncontrolled Format String)";
200 const char GenericTaintChecker::MsgSanitizeSystemArgs[] =
201 "Untrusted data is passed to a system call "
202 "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
204 const char GenericTaintChecker::MsgTaintedBufferSize[] =
205 "Untrusted data is used to specify the buffer size "
206 "(CERT/STR31-C. Guarantee that storage for strings has sufficient space for "
207 "character data and the null terminator)";
209 } // end of anonymous namespace
211 /// A set which is used to pass information from call pre-visit instruction
212 /// to the call post-visit. The values are unsigned integers, which are either
213 /// ReturnValueIndex, or indexes of the pointer/reference argument, which
214 /// points to data, which should be tainted on return.
215 REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned)
217 std::shared_ptr<PathDiagnosticPiece>
218 GenericTaintChecker::TaintBugVisitor::VisitNode(const ExplodedNode *N,
219 const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) {
221 // Find the ExplodedNode where the taint was first introduced
222 if (!N->getState()->isTainted(V) || PrevN->getState()->isTainted(V))
225 const Stmt *S = PathDiagnosticLocation::getStmt(N);
229 const LocationContext *NCtx = N->getLocationContext();
230 PathDiagnosticLocation L =
231 PathDiagnosticLocation::createBegin(S, BRC.getSourceManager(), NCtx);
232 if (!L.isValid() || !L.asLocation().isValid())
235 return std::make_shared<PathDiagnosticEventPiece>(
236 L, "Taint originated here");
239 GenericTaintChecker::TaintPropagationRule
240 GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
241 const FunctionDecl *FDecl,
244 // TODO: Currently, we might lose precision here: we always mark a return
245 // value as tainted even if it's just a pointer, pointing to tainted data.
247 // Check for exact name match for functions without builtin substitutes.
248 TaintPropagationRule Rule = llvm::StringSwitch<TaintPropagationRule>(Name)
249 .Case("atoi", TaintPropagationRule(0, ReturnValueIndex))
250 .Case("atol", TaintPropagationRule(0, ReturnValueIndex))
251 .Case("atoll", TaintPropagationRule(0, ReturnValueIndex))
252 .Case("getc", TaintPropagationRule(0, ReturnValueIndex))
253 .Case("fgetc", TaintPropagationRule(0, ReturnValueIndex))
254 .Case("getc_unlocked", TaintPropagationRule(0, ReturnValueIndex))
255 .Case("getw", TaintPropagationRule(0, ReturnValueIndex))
256 .Case("toupper", TaintPropagationRule(0, ReturnValueIndex))
257 .Case("tolower", TaintPropagationRule(0, ReturnValueIndex))
258 .Case("strchr", TaintPropagationRule(0, ReturnValueIndex))
259 .Case("strrchr", TaintPropagationRule(0, ReturnValueIndex))
260 .Case("read", TaintPropagationRule(0, 2, 1, true))
261 .Case("pread", TaintPropagationRule(InvalidArgIndex, 1, true))
262 .Case("gets", TaintPropagationRule(InvalidArgIndex, 0, true))
263 .Case("fgets", TaintPropagationRule(2, 0, true))
264 .Case("getline", TaintPropagationRule(2, 0))
265 .Case("getdelim", TaintPropagationRule(3, 0))
266 .Case("fgetln", TaintPropagationRule(0, ReturnValueIndex))
267 .Default(TaintPropagationRule());
272 // Check if it's one of the memory setting/copying functions.
273 // This check is specialized but faster then calling isCLibraryFunction.
275 if ( (BId = FDecl->getMemoryFunctionKind()) )
277 case Builtin::BImemcpy:
278 case Builtin::BImemmove:
279 case Builtin::BIstrncpy:
280 case Builtin::BIstrncat:
281 return TaintPropagationRule(1, 2, 0, true);
282 case Builtin::BIstrlcpy:
283 case Builtin::BIstrlcat:
284 return TaintPropagationRule(1, 2, 0, false);
285 case Builtin::BIstrndup:
286 return TaintPropagationRule(0, 1, ReturnValueIndex);
292 // Process all other functions which could be defined as builtins.
294 if (C.isCLibraryFunction(FDecl, "snprintf") ||
295 C.isCLibraryFunction(FDecl, "sprintf"))
296 return TaintPropagationRule(InvalidArgIndex, 0, true);
297 else if (C.isCLibraryFunction(FDecl, "strcpy") ||
298 C.isCLibraryFunction(FDecl, "stpcpy") ||
299 C.isCLibraryFunction(FDecl, "strcat"))
300 return TaintPropagationRule(1, 0, true);
301 else if (C.isCLibraryFunction(FDecl, "bcopy"))
302 return TaintPropagationRule(0, 2, 1, false);
303 else if (C.isCLibraryFunction(FDecl, "strdup") ||
304 C.isCLibraryFunction(FDecl, "strdupa"))
305 return TaintPropagationRule(0, ReturnValueIndex);
306 else if (C.isCLibraryFunction(FDecl, "wcsdup"))
307 return TaintPropagationRule(0, ReturnValueIndex);
310 // Skipping the following functions, since they might be used for cleansing
311 // or smart memory copy:
312 // - memccpy - copying until hitting a special character.
314 return TaintPropagationRule();
317 void GenericTaintChecker::checkPreStmt(const CallExpr *CE,
318 CheckerContext &C) const {
319 // Check for errors first.
324 addSourcesPre(CE, C);
327 void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
328 CheckerContext &C) const {
329 if (propagateFromPre(CE, C))
331 addSourcesPost(CE, C);
334 void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
335 CheckerContext &C) const {
336 ProgramStateRef State = nullptr;
337 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
338 if (!FDecl || FDecl->getKind() != Decl::Function)
341 StringRef Name = C.getCalleeName(FDecl);
345 // First, try generating a propagation rule for this function.
346 TaintPropagationRule Rule =
347 TaintPropagationRule::getTaintPropagationRule(FDecl, Name, C);
348 if (!Rule.isNull()) {
349 State = Rule.process(CE, C);
352 C.addTransition(State);
356 // Otherwise, check if we have custom pre-processing implemented.
357 FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
358 .Case("fscanf", &GenericTaintChecker::preFscanf)
360 // Check and evaluate the call.
362 State = (this->*evalFunction)(CE, C);
365 C.addTransition(State);
369 bool GenericTaintChecker::propagateFromPre(const CallExpr *CE,
370 CheckerContext &C) const {
371 ProgramStateRef State = C.getState();
373 // Depending on what was tainted at pre-visit, we determined a set of
374 // arguments which should be tainted after the function returns. These are
375 // stored in the state as TaintArgsOnPostVisit set.
376 TaintArgsOnPostVisitTy TaintArgs = State->get<TaintArgsOnPostVisit>();
377 if (TaintArgs.isEmpty())
380 for (llvm::ImmutableSet<unsigned>::iterator
381 I = TaintArgs.begin(), E = TaintArgs.end(); I != E; ++I) {
382 unsigned ArgNum = *I;
384 // Special handling for the tainted return value.
385 if (ArgNum == ReturnValueIndex) {
386 State = State->addTaint(CE, C.getLocationContext());
390 // The arguments are pointer arguments. The data they are pointing at is
391 // tainted after the call.
392 if (CE->getNumArgs() < (ArgNum + 1))
394 const Expr* Arg = CE->getArg(ArgNum);
395 Optional<SVal> V = getPointedToSVal(C, Arg);
397 State = State->addTaint(*V);
400 // Clear up the taint info from the state.
401 State = State->remove<TaintArgsOnPostVisit>();
403 if (State != C.getState()) {
404 C.addTransition(State);
410 void GenericTaintChecker::addSourcesPost(const CallExpr *CE,
411 CheckerContext &C) const {
412 // Define the attack surface.
413 // Set the evaluation function by switching on the callee name.
414 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
415 if (!FDecl || FDecl->getKind() != Decl::Function)
418 StringRef Name = C.getCalleeName(FDecl);
421 FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
422 .Case("scanf", &GenericTaintChecker::postScanf)
423 // TODO: Add support for vfscanf & family.
424 .Case("getchar", &GenericTaintChecker::postRetTaint)
425 .Case("getchar_unlocked", &GenericTaintChecker::postRetTaint)
426 .Case("getenv", &GenericTaintChecker::postRetTaint)
427 .Case("fopen", &GenericTaintChecker::postRetTaint)
428 .Case("fdopen", &GenericTaintChecker::postRetTaint)
429 .Case("freopen", &GenericTaintChecker::postRetTaint)
430 .Case("getch", &GenericTaintChecker::postRetTaint)
431 .Case("wgetch", &GenericTaintChecker::postRetTaint)
432 .Case("socket", &GenericTaintChecker::postSocket)
435 // If the callee isn't defined, it is not of security concern.
436 // Check and evaluate the call.
437 ProgramStateRef State = nullptr;
439 State = (this->*evalFunction)(CE, C);
443 C.addTransition(State);
446 bool GenericTaintChecker::checkPre(const CallExpr *CE, CheckerContext &C) const{
448 if (checkUncontrolledFormatString(CE, C))
451 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
452 if (!FDecl || FDecl->getKind() != Decl::Function)
455 StringRef Name = C.getCalleeName(FDecl);
459 if (checkSystemCall(CE, Name, C))
462 if (checkTaintedBufferSize(CE, FDecl, C))
468 Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
470 ProgramStateRef State = C.getState();
471 SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext());
472 if (AddrVal.isUnknownOrUndef())
475 Optional<Loc> AddrLoc = AddrVal.getAs<Loc>();
479 const PointerType *ArgTy =
480 dyn_cast<PointerType>(Arg->getType().getCanonicalType().getTypePtr());
481 return State->getSVal(*AddrLoc, ArgTy ? ArgTy->getPointeeType(): QualType());
485 GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
486 CheckerContext &C) const {
487 ProgramStateRef State = C.getState();
489 // Check for taint in arguments.
490 bool IsTainted = false;
491 for (ArgVector::const_iterator I = SrcArgs.begin(),
492 E = SrcArgs.end(); I != E; ++I) {
493 unsigned ArgNum = *I;
495 if (ArgNum == InvalidArgIndex) {
496 // Check if any of the arguments is tainted, but skip the
497 // destination arguments.
498 for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
499 if (isDestinationArgument(i))
501 if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(i), State, C)))
507 if (CE->getNumArgs() < (ArgNum + 1))
509 if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(ArgNum), State, C)))
515 // Mark the arguments which should be tainted after the function returns.
516 for (ArgVector::const_iterator I = DstArgs.begin(),
517 E = DstArgs.end(); I != E; ++I) {
518 unsigned ArgNum = *I;
520 // Should we mark all arguments as tainted?
521 if (ArgNum == InvalidArgIndex) {
522 // For all pointer and references that were passed in:
523 // If they are not pointing to const data, mark data as tainted.
524 // TODO: So far we are just going one level down; ideally we'd need to
526 for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
527 const Expr *Arg = CE->getArg(i);
528 // Process pointer argument.
529 const Type *ArgTy = Arg->getType().getTypePtr();
530 QualType PType = ArgTy->getPointeeType();
531 if ((!PType.isNull() && !PType.isConstQualified())
532 || (ArgTy->isReferenceType() && !Arg->getType().isConstQualified()))
533 State = State->add<TaintArgsOnPostVisit>(i);
538 // Should mark the return value?
539 if (ArgNum == ReturnValueIndex) {
540 State = State->add<TaintArgsOnPostVisit>(ReturnValueIndex);
544 // Mark the given argument.
545 assert(ArgNum < CE->getNumArgs());
546 State = State->add<TaintArgsOnPostVisit>(ArgNum);
553 // If argument 0 (file descriptor) is tainted, all arguments except for arg 0
554 // and arg 1 should get taint.
555 ProgramStateRef GenericTaintChecker::preFscanf(const CallExpr *CE,
556 CheckerContext &C) const {
557 assert(CE->getNumArgs() >= 2);
558 ProgramStateRef State = C.getState();
560 // Check is the file descriptor is tainted.
561 if (State->isTainted(CE->getArg(0), C.getLocationContext()) ||
562 isStdin(CE->getArg(0), C)) {
563 // All arguments except for the first two should get taint.
564 for (unsigned int i = 2; i < CE->getNumArgs(); ++i)
565 State = State->add<TaintArgsOnPostVisit>(i);
573 // If argument 0(protocol domain) is network, the return value should get taint.
574 ProgramStateRef GenericTaintChecker::postSocket(const CallExpr *CE,
575 CheckerContext &C) const {
576 ProgramStateRef State = C.getState();
577 if (CE->getNumArgs() < 3)
580 SourceLocation DomLoc = CE->getArg(0)->getExprLoc();
581 StringRef DomName = C.getMacroNameOrSpelling(DomLoc);
582 // White list the internal communication protocols.
583 if (DomName.equals("AF_SYSTEM") || DomName.equals("AF_LOCAL") ||
584 DomName.equals("AF_UNIX") || DomName.equals("AF_RESERVED_36"))
586 State = State->addTaint(CE, C.getLocationContext());
590 ProgramStateRef GenericTaintChecker::postScanf(const CallExpr *CE,
591 CheckerContext &C) const {
592 ProgramStateRef State = C.getState();
593 if (CE->getNumArgs() < 2)
596 // All arguments except for the very first one should get taint.
597 for (unsigned int i = 1; i < CE->getNumArgs(); ++i) {
598 // The arguments are pointer arguments. The data they are pointing at is
599 // tainted after the call.
600 const Expr* Arg = CE->getArg(i);
601 Optional<SVal> V = getPointedToSVal(C, Arg);
603 State = State->addTaint(*V);
608 ProgramStateRef GenericTaintChecker::postRetTaint(const CallExpr *CE,
609 CheckerContext &C) const {
610 return C.getState()->addTaint(CE, C.getLocationContext());
613 bool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) {
614 ProgramStateRef State = C.getState();
615 SVal Val = State->getSVal(E, C.getLocationContext());
617 // stdin is a pointer, so it would be a region.
618 const MemRegion *MemReg = Val.getAsRegion();
620 // The region should be symbolic, we do not know it's value.
621 const SymbolicRegion *SymReg = dyn_cast_or_null<SymbolicRegion>(MemReg);
625 // Get it's symbol and find the declaration region it's pointing to.
626 const SymbolRegionValue *Sm =dyn_cast<SymbolRegionValue>(SymReg->getSymbol());
629 const DeclRegion *DeclReg = dyn_cast_or_null<DeclRegion>(Sm->getRegion());
633 // This region corresponds to a declaration, find out if it's a global/extern
634 // variable named stdin with the proper type.
635 if (const VarDecl *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) {
636 D = D->getCanonicalDecl();
637 if ((D->getName().find("stdin") != StringRef::npos) && D->isExternC())
638 if (const PointerType * PtrTy =
639 dyn_cast<PointerType>(D->getType().getTypePtr()))
640 if (PtrTy->getPointeeType() == C.getASTContext().getFILEType())
646 static bool getPrintfFormatArgumentNum(const CallExpr *CE,
647 const CheckerContext &C,
648 unsigned int &ArgNum) {
649 // Find if the function contains a format string argument.
650 // Handles: fprintf, printf, sprintf, snprintf, vfprintf, vprintf, vsprintf,
651 // vsnprintf, syslog, custom annotated functions.
652 const FunctionDecl *FDecl = C.getCalleeDecl(CE);
655 for (const auto *Format : FDecl->specific_attrs<FormatAttr>()) {
656 ArgNum = Format->getFormatIdx() - 1;
657 if ((Format->getType()->getName() == "printf") &&
658 CE->getNumArgs() > ArgNum)
662 // Or if a function is named setproctitle (this is a heuristic).
663 if (C.getCalleeName(CE).find("setproctitle") != StringRef::npos) {
671 bool GenericTaintChecker::generateReportIfTainted(const Expr *E,
673 CheckerContext &C) const {
677 ProgramStateRef State = C.getState();
678 Optional<SVal> PointedToSVal = getPointedToSVal(C, E);
680 if (PointedToSVal && State->isTainted(*PointedToSVal))
681 TaintedSVal = *PointedToSVal;
682 else if (State->isTainted(E, C.getLocationContext()))
683 TaintedSVal = C.getSVal(E);
687 // Generate diagnostic.
688 if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
690 auto report = llvm::make_unique<BugReport>(*BT, Msg, N);
691 report->addRange(E->getSourceRange());
692 report->addVisitor(llvm::make_unique<TaintBugVisitor>(TaintedSVal));
693 C.emitReport(std::move(report));
699 bool GenericTaintChecker::checkUncontrolledFormatString(const CallExpr *CE,
700 CheckerContext &C) const{
701 // Check if the function contains a format string argument.
702 unsigned int ArgNum = 0;
703 if (!getPrintfFormatArgumentNum(CE, C, ArgNum))
706 // If either the format string content or the pointer itself are tainted, warn.
707 return generateReportIfTainted(CE->getArg(ArgNum),
708 MsgUncontrolledFormatString, C);
711 bool GenericTaintChecker::checkSystemCall(const CallExpr *CE,
713 CheckerContext &C) const {
714 // TODO: It might make sense to run this check on demand. In some cases,
715 // we should check if the environment has been cleansed here. We also might
716 // need to know if the user was reset before these calls(seteuid).
717 unsigned ArgNum = llvm::StringSwitch<unsigned>(Name)
730 if (ArgNum == UINT_MAX || CE->getNumArgs() < (ArgNum + 1))
733 return generateReportIfTainted(CE->getArg(ArgNum), MsgSanitizeSystemArgs, C);
736 // TODO: Should this check be a part of the CString checker?
737 // If yes, should taint be a global setting?
738 bool GenericTaintChecker::checkTaintedBufferSize(const CallExpr *CE,
739 const FunctionDecl *FDecl,
740 CheckerContext &C) const {
741 // If the function has a buffer size argument, set ArgNum.
742 unsigned ArgNum = InvalidArgIndex;
744 if ( (BId = FDecl->getMemoryFunctionKind()) )
746 case Builtin::BImemcpy:
747 case Builtin::BImemmove:
748 case Builtin::BIstrncpy:
751 case Builtin::BIstrndup:
758 if (ArgNum == InvalidArgIndex) {
759 if (C.isCLibraryFunction(FDecl, "malloc") ||
760 C.isCLibraryFunction(FDecl, "calloc") ||
761 C.isCLibraryFunction(FDecl, "alloca"))
763 else if (C.isCLibraryFunction(FDecl, "memccpy"))
765 else if (C.isCLibraryFunction(FDecl, "realloc"))
767 else if (C.isCLibraryFunction(FDecl, "bcopy"))
771 return ArgNum != InvalidArgIndex && CE->getNumArgs() > ArgNum &&
772 generateReportIfTainted(CE->getArg(ArgNum), MsgTaintedBufferSize, C);
775 void ento::registerGenericTaintChecker(CheckerManager &mgr) {
776 mgr.registerChecker<GenericTaintChecker>();