GenericTaintChecker.cpp revision 353358
1//== GenericTaintChecker.cpp ----------------------------------- -*- C++ -*--=//
2//
3// 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
6//
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//===----------------------------------------------------------------------===//
16
17#include "Taint.h"
18#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
19#include "clang/AST/Attr.h"
20#include "clang/Basic/Builtins.h"
21#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
22#include "clang/StaticAnalyzer/Core/Checker.h"
23#include "clang/StaticAnalyzer/Core/CheckerManager.h"
24#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
25#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
26#include <climits>
27#include <initializer_list>
28#include <utility>
29
30using namespace clang;
31using namespace ento;
32using namespace taint;
33
34namespace {
35class GenericTaintChecker
36    : public Checker<check::PostStmt<CallExpr>, check::PreStmt<CallExpr>> {
37public:
38  static void *getTag() {
39    static int Tag;
40    return &Tag;
41  }
42
43  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
44
45  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
46
47  void printState(raw_ostream &Out, ProgramStateRef State,
48                  const char *NL, const char *Sep) const override;
49
50private:
51  static const unsigned InvalidArgIndex = UINT_MAX;
52  /// Denotes the return vale.
53  static const unsigned ReturnValueIndex = UINT_MAX - 1;
54
55  mutable std::unique_ptr<BugType> BT;
56  void initBugType() const {
57    if (!BT)
58      BT.reset(new BugType(this, "Use of Untrusted Data", "Untrusted Data"));
59  }
60
61  /// Catch taint related bugs. Check if tainted data is passed to a
62  /// system call etc.
63  bool checkPre(const CallExpr *CE, CheckerContext &C) const;
64
65  /// Add taint sources on a pre-visit.
66  void addSourcesPre(const CallExpr *CE, CheckerContext &C) const;
67
68  /// Propagate taint generated at pre-visit.
69  bool propagateFromPre(const CallExpr *CE, CheckerContext &C) const;
70
71  /// Check if the region the expression evaluates to is the standard input,
72  /// and thus, is tainted.
73  static bool isStdin(const Expr *E, CheckerContext &C);
74
75  /// Given a pointer argument, return the value it points to.
76  static Optional<SVal> getPointedToSVal(CheckerContext &C, const Expr *Arg);
77
78  /// Check for CWE-134: Uncontrolled Format String.
79  static const char MsgUncontrolledFormatString[];
80  bool checkUncontrolledFormatString(const CallExpr *CE,
81                                     CheckerContext &C) const;
82
83  /// Check for:
84  /// CERT/STR02-C. "Sanitize data passed to complex subsystems"
85  /// CWE-78, "Failure to Sanitize Data into an OS Command"
86  static const char MsgSanitizeSystemArgs[];
87  bool checkSystemCall(const CallExpr *CE, StringRef Name,
88                       CheckerContext &C) const;
89
90  /// Check if tainted data is used as a buffer size ins strn.. functions,
91  /// and allocators.
92  static const char MsgTaintedBufferSize[];
93  bool checkTaintedBufferSize(const CallExpr *CE, const FunctionDecl *FDecl,
94                              CheckerContext &C) const;
95
96  /// Generate a report if the expression is tainted or points to tainted data.
97  bool generateReportIfTainted(const Expr *E, const char Msg[],
98                               CheckerContext &C) const;
99
100  using ArgVector = SmallVector<unsigned, 2>;
101
102  /// A struct used to specify taint propagation rules for a function.
103  ///
104  /// If any of the possible taint source arguments is tainted, all of the
105  /// destination arguments should also be tainted. Use InvalidArgIndex in the
106  /// src list to specify that all of the arguments can introduce taint. Use
107  /// InvalidArgIndex in the dst arguments to signify that all the non-const
108  /// pointer and reference arguments might be tainted on return. If
109  /// ReturnValueIndex is added to the dst list, the return value will be
110  /// tainted.
111  struct TaintPropagationRule {
112    enum class VariadicType { None, Src, Dst };
113
114    using PropagationFuncType = bool (*)(bool IsTainted, const CallExpr *,
115                                         CheckerContext &C);
116
117    /// List of arguments which can be taint sources and should be checked.
118    ArgVector SrcArgs;
119    /// List of arguments which should be tainted on function return.
120    ArgVector DstArgs;
121    /// Index for the first variadic parameter if exist.
122    unsigned VariadicIndex;
123    /// Show when a function has variadic parameters. If it has, it marks all
124    /// of them as source or destination.
125    VariadicType VarType;
126    /// Special function for tainted source determination. If defined, it can
127    /// override the default behavior.
128    PropagationFuncType PropagationFunc;
129
130    TaintPropagationRule()
131        : VariadicIndex(InvalidArgIndex), VarType(VariadicType::None),
132          PropagationFunc(nullptr) {}
133
134    TaintPropagationRule(std::initializer_list<unsigned> &&Src,
135                         std::initializer_list<unsigned> &&Dst,
136                         VariadicType Var = VariadicType::None,
137                         unsigned VarIndex = InvalidArgIndex,
138                         PropagationFuncType Func = nullptr)
139        : SrcArgs(std::move(Src)), DstArgs(std::move(Dst)),
140          VariadicIndex(VarIndex), VarType(Var), PropagationFunc(Func) {}
141
142    /// Get the propagation rule for a given function.
143    static TaintPropagationRule
144    getTaintPropagationRule(const FunctionDecl *FDecl, StringRef Name,
145                            CheckerContext &C);
146
147    void addSrcArg(unsigned A) { SrcArgs.push_back(A); }
148    void addDstArg(unsigned A) { DstArgs.push_back(A); }
149
150    bool isNull() const {
151      return SrcArgs.empty() && DstArgs.empty() &&
152             VariadicType::None == VarType;
153    }
154
155    bool isDestinationArgument(unsigned ArgNum) const {
156      return (llvm::find(DstArgs, ArgNum) != DstArgs.end());
157    }
158
159    static bool isTaintedOrPointsToTainted(const Expr *E, ProgramStateRef State,
160                                           CheckerContext &C) {
161      if (isTainted(State, E, C.getLocationContext()) || isStdin(E, C))
162        return true;
163
164      if (!E->getType().getTypePtr()->isPointerType())
165        return false;
166
167      Optional<SVal> V = getPointedToSVal(C, E);
168      return (V && isTainted(State, *V));
169    }
170
171    /// Pre-process a function which propagates taint according to the
172    /// taint rule.
173    ProgramStateRef process(const CallExpr *CE, CheckerContext &C) const;
174
175    // Functions for custom taintedness propagation.
176    static bool postSocket(bool IsTainted, const CallExpr *CE,
177                           CheckerContext &C);
178  };
179};
180
181const unsigned GenericTaintChecker::ReturnValueIndex;
182const unsigned GenericTaintChecker::InvalidArgIndex;
183
184const char GenericTaintChecker::MsgUncontrolledFormatString[] =
185    "Untrusted data is used as a format string "
186    "(CWE-134: Uncontrolled Format String)";
187
188const char GenericTaintChecker::MsgSanitizeSystemArgs[] =
189    "Untrusted data is passed to a system call "
190    "(CERT/STR02-C. Sanitize data passed to complex subsystems)";
191
192const char GenericTaintChecker::MsgTaintedBufferSize[] =
193    "Untrusted data is used to specify the buffer size "
194    "(CERT/STR31-C. Guarantee that storage for strings has sufficient space "
195    "for character data and the null terminator)";
196
197} // end of anonymous namespace
198
199/// A set which is used to pass information from call pre-visit instruction
200/// to the call post-visit. The values are unsigned integers, which are either
201/// ReturnValueIndex, or indexes of the pointer/reference argument, which
202/// points to data, which should be tainted on return.
203REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned)
204
205GenericTaintChecker::TaintPropagationRule
206GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule(
207    const FunctionDecl *FDecl, StringRef Name, CheckerContext &C) {
208  // TODO: Currently, we might lose precision here: we always mark a return
209  // value as tainted even if it's just a pointer, pointing to tainted data.
210
211  // Check for exact name match for functions without builtin substitutes.
212  TaintPropagationRule Rule =
213      llvm::StringSwitch<TaintPropagationRule>(Name)
214          // Source functions
215          // TODO: Add support for vfscanf & family.
216          .Case("fdopen", TaintPropagationRule({}, {ReturnValueIndex}))
217          .Case("fopen", TaintPropagationRule({}, {ReturnValueIndex}))
218          .Case("freopen", TaintPropagationRule({}, {ReturnValueIndex}))
219          .Case("getch", TaintPropagationRule({}, {ReturnValueIndex}))
220          .Case("getchar", TaintPropagationRule({}, {ReturnValueIndex}))
221          .Case("getchar_unlocked", TaintPropagationRule({}, {ReturnValueIndex}))
222          .Case("getenv", TaintPropagationRule({}, {ReturnValueIndex}))
223          .Case("gets", TaintPropagationRule({}, {0, ReturnValueIndex}))
224          .Case("scanf", TaintPropagationRule({}, {}, VariadicType::Dst, 1))
225          .Case("socket",
226                TaintPropagationRule({}, {ReturnValueIndex}, VariadicType::None,
227                                     InvalidArgIndex,
228                                     &TaintPropagationRule::postSocket))
229          .Case("wgetch", TaintPropagationRule({}, {ReturnValueIndex}))
230          // Propagating functions
231          .Case("atoi", TaintPropagationRule({0}, {ReturnValueIndex}))
232          .Case("atol", TaintPropagationRule({0}, {ReturnValueIndex}))
233          .Case("atoll", TaintPropagationRule({0}, {ReturnValueIndex}))
234          .Case("fgetc", TaintPropagationRule({0}, {ReturnValueIndex}))
235          .Case("fgetln", TaintPropagationRule({0}, {ReturnValueIndex}))
236          .Case("fgets", TaintPropagationRule({2}, {0, ReturnValueIndex}))
237          .Case("fscanf", TaintPropagationRule({0}, {}, VariadicType::Dst, 2))
238          .Case("getc", TaintPropagationRule({0}, {ReturnValueIndex}))
239          .Case("getc_unlocked", TaintPropagationRule({0}, {ReturnValueIndex}))
240          .Case("getdelim", TaintPropagationRule({3}, {0}))
241          .Case("getline", TaintPropagationRule({2}, {0}))
242          .Case("getw", TaintPropagationRule({0}, {ReturnValueIndex}))
243          .Case("pread",
244                TaintPropagationRule({0, 1, 2, 3}, {1, ReturnValueIndex}))
245          .Case("read", TaintPropagationRule({0, 2}, {1, ReturnValueIndex}))
246          .Case("strchr", TaintPropagationRule({0}, {ReturnValueIndex}))
247          .Case("strrchr", TaintPropagationRule({0}, {ReturnValueIndex}))
248          .Case("tolower", TaintPropagationRule({0}, {ReturnValueIndex}))
249          .Case("toupper", TaintPropagationRule({0}, {ReturnValueIndex}))
250          .Default(TaintPropagationRule());
251
252  if (!Rule.isNull())
253    return Rule;
254
255  // Check if it's one of the memory setting/copying functions.
256  // This check is specialized but faster then calling isCLibraryFunction.
257  unsigned BId = 0;
258  if ((BId = FDecl->getMemoryFunctionKind()))
259    switch (BId) {
260    case Builtin::BImemcpy:
261    case Builtin::BImemmove:
262    case Builtin::BIstrncpy:
263    case Builtin::BIstrncat:
264      return TaintPropagationRule({1, 2}, {0, ReturnValueIndex});
265    case Builtin::BIstrlcpy:
266    case Builtin::BIstrlcat:
267      return TaintPropagationRule({1, 2}, {0});
268    case Builtin::BIstrndup:
269      return TaintPropagationRule({0, 1}, {ReturnValueIndex});
270
271    default:
272      break;
273    };
274
275  // Process all other functions which could be defined as builtins.
276  if (Rule.isNull()) {
277    if (C.isCLibraryFunction(FDecl, "snprintf"))
278      return TaintPropagationRule({1}, {0, ReturnValueIndex}, VariadicType::Src,
279                                  3);
280    else if (C.isCLibraryFunction(FDecl, "sprintf"))
281      return TaintPropagationRule({}, {0, ReturnValueIndex}, VariadicType::Src,
282                                  2);
283    else if (C.isCLibraryFunction(FDecl, "strcpy") ||
284             C.isCLibraryFunction(FDecl, "stpcpy") ||
285             C.isCLibraryFunction(FDecl, "strcat"))
286      return TaintPropagationRule({1}, {0, ReturnValueIndex});
287    else if (C.isCLibraryFunction(FDecl, "bcopy"))
288      return TaintPropagationRule({0, 2}, {1});
289    else if (C.isCLibraryFunction(FDecl, "strdup") ||
290             C.isCLibraryFunction(FDecl, "strdupa"))
291      return TaintPropagationRule({0}, {ReturnValueIndex});
292    else if (C.isCLibraryFunction(FDecl, "wcsdup"))
293      return TaintPropagationRule({0}, {ReturnValueIndex});
294  }
295
296  // Skipping the following functions, since they might be used for cleansing
297  // or smart memory copy:
298  // - memccpy - copying until hitting a special character.
299
300  return TaintPropagationRule();
301}
302
303void GenericTaintChecker::checkPreStmt(const CallExpr *CE,
304                                       CheckerContext &C) const {
305  // Check for taintedness related errors first: system call, uncontrolled
306  // format string, tainted buffer size.
307  if (checkPre(CE, C))
308    return;
309
310  // Marks the function's arguments and/or return value tainted if it present in
311  // the list.
312  addSourcesPre(CE, C);
313}
314
315void GenericTaintChecker::checkPostStmt(const CallExpr *CE,
316                                        CheckerContext &C) const {
317  // Set the marked values as tainted. The return value only accessible from
318  // checkPostStmt.
319  propagateFromPre(CE, C);
320}
321
322void GenericTaintChecker::printState(raw_ostream &Out, ProgramStateRef State,
323                                     const char *NL, const char *Sep) const {
324  printTaint(State, Out, NL, Sep);
325}
326
327void GenericTaintChecker::addSourcesPre(const CallExpr *CE,
328                                        CheckerContext &C) const {
329  ProgramStateRef State = nullptr;
330  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
331  if (!FDecl || FDecl->getKind() != Decl::Function)
332    return;
333
334  StringRef Name = C.getCalleeName(FDecl);
335  if (Name.empty())
336    return;
337
338  // First, try generating a propagation rule for this function.
339  TaintPropagationRule Rule =
340      TaintPropagationRule::getTaintPropagationRule(FDecl, Name, C);
341  if (!Rule.isNull()) {
342    State = Rule.process(CE, C);
343    if (!State)
344      return;
345    C.addTransition(State);
346    return;
347  }
348
349  if (!State)
350    return;
351  C.addTransition(State);
352}
353
354bool GenericTaintChecker::propagateFromPre(const CallExpr *CE,
355                                           CheckerContext &C) const {
356  ProgramStateRef State = C.getState();
357
358  // Depending on what was tainted at pre-visit, we determined a set of
359  // arguments which should be tainted after the function returns. These are
360  // stored in the state as TaintArgsOnPostVisit set.
361  TaintArgsOnPostVisitTy TaintArgs = State->get<TaintArgsOnPostVisit>();
362  if (TaintArgs.isEmpty())
363    return false;
364
365  for (unsigned ArgNum : TaintArgs) {
366    // Special handling for the tainted return value.
367    if (ArgNum == ReturnValueIndex) {
368      State = addTaint(State, CE, C.getLocationContext());
369      continue;
370    }
371
372    // The arguments are pointer arguments. The data they are pointing at is
373    // tainted after the call.
374    if (CE->getNumArgs() < (ArgNum + 1))
375      return false;
376    const Expr *Arg = CE->getArg(ArgNum);
377    Optional<SVal> V = getPointedToSVal(C, Arg);
378    if (V)
379      State = addTaint(State, *V);
380  }
381
382  // Clear up the taint info from the state.
383  State = State->remove<TaintArgsOnPostVisit>();
384
385  if (State != C.getState()) {
386    C.addTransition(State);
387    return true;
388  }
389  return false;
390}
391
392bool GenericTaintChecker::checkPre(const CallExpr *CE,
393                                   CheckerContext &C) const {
394
395  if (checkUncontrolledFormatString(CE, C))
396    return true;
397
398  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
399  if (!FDecl || FDecl->getKind() != Decl::Function)
400    return false;
401
402  StringRef Name = C.getCalleeName(FDecl);
403  if (Name.empty())
404    return false;
405
406  if (checkSystemCall(CE, Name, C))
407    return true;
408
409  if (checkTaintedBufferSize(CE, FDecl, C))
410    return true;
411
412  return false;
413}
414
415Optional<SVal> GenericTaintChecker::getPointedToSVal(CheckerContext &C,
416                                                     const Expr *Arg) {
417  ProgramStateRef State = C.getState();
418  SVal AddrVal = C.getSVal(Arg->IgnoreParens());
419  if (AddrVal.isUnknownOrUndef())
420    return None;
421
422  Optional<Loc> AddrLoc = AddrVal.getAs<Loc>();
423  if (!AddrLoc)
424    return None;
425
426  QualType ArgTy = Arg->getType().getCanonicalType();
427  if (!ArgTy->isPointerType())
428    return None;
429
430  QualType ValTy = ArgTy->getPointeeType();
431
432  // Do not dereference void pointers. Treat them as byte pointers instead.
433  // FIXME: we might want to consider more than just the first byte.
434  if (ValTy->isVoidType())
435    ValTy = C.getASTContext().CharTy;
436
437  return State->getSVal(*AddrLoc, ValTy);
438}
439
440ProgramStateRef
441GenericTaintChecker::TaintPropagationRule::process(const CallExpr *CE,
442                                                   CheckerContext &C) const {
443  ProgramStateRef State = C.getState();
444
445  // Check for taint in arguments.
446  bool IsTainted = true;
447  for (unsigned ArgNum : SrcArgs) {
448    if (ArgNum >= CE->getNumArgs())
449      return State;
450    if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(ArgNum), State, C)))
451      break;
452  }
453
454  // Check for taint in variadic arguments.
455  if (!IsTainted && VariadicType::Src == VarType) {
456    // Check if any of the arguments is tainted
457    for (unsigned int i = VariadicIndex; i < CE->getNumArgs(); ++i) {
458      if ((IsTainted = isTaintedOrPointsToTainted(CE->getArg(i), State, C)))
459        break;
460    }
461  }
462
463  if (PropagationFunc)
464    IsTainted = PropagationFunc(IsTainted, CE, C);
465
466  if (!IsTainted)
467    return State;
468
469  // Mark the arguments which should be tainted after the function returns.
470  for (unsigned ArgNum : DstArgs) {
471    // Should mark the return value?
472    if (ArgNum == ReturnValueIndex) {
473      State = State->add<TaintArgsOnPostVisit>(ReturnValueIndex);
474      continue;
475    }
476
477    // Mark the given argument.
478    assert(ArgNum < CE->getNumArgs());
479    State = State->add<TaintArgsOnPostVisit>(ArgNum);
480  }
481
482  // Mark all variadic arguments tainted if present.
483  if (VariadicType::Dst == VarType) {
484    // For all pointer and references that were passed in:
485    //   If they are not pointing to const data, mark data as tainted.
486    //   TODO: So far we are just going one level down; ideally we'd need to
487    //         recurse here.
488    for (unsigned int i = VariadicIndex; i < CE->getNumArgs(); ++i) {
489      const Expr *Arg = CE->getArg(i);
490      // Process pointer argument.
491      const Type *ArgTy = Arg->getType().getTypePtr();
492      QualType PType = ArgTy->getPointeeType();
493      if ((!PType.isNull() && !PType.isConstQualified()) ||
494          (ArgTy->isReferenceType() && !Arg->getType().isConstQualified()))
495        State = State->add<TaintArgsOnPostVisit>(i);
496    }
497  }
498
499  return State;
500}
501
502// If argument 0(protocol domain) is network, the return value should get taint.
503bool GenericTaintChecker::TaintPropagationRule::postSocket(bool /*IsTainted*/,
504                                                           const CallExpr *CE,
505                                                           CheckerContext &C) {
506  SourceLocation DomLoc = CE->getArg(0)->getExprLoc();
507  StringRef DomName = C.getMacroNameOrSpelling(DomLoc);
508  // White list the internal communication protocols.
509  if (DomName.equals("AF_SYSTEM") || DomName.equals("AF_LOCAL") ||
510      DomName.equals("AF_UNIX") || DomName.equals("AF_RESERVED_36"))
511    return false;
512
513  return true;
514}
515
516bool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) {
517  ProgramStateRef State = C.getState();
518  SVal Val = C.getSVal(E);
519
520  // stdin is a pointer, so it would be a region.
521  const MemRegion *MemReg = Val.getAsRegion();
522
523  // The region should be symbolic, we do not know it's value.
524  const SymbolicRegion *SymReg = dyn_cast_or_null<SymbolicRegion>(MemReg);
525  if (!SymReg)
526    return false;
527
528  // Get it's symbol and find the declaration region it's pointing to.
529  const SymbolRegionValue *Sm =
530      dyn_cast<SymbolRegionValue>(SymReg->getSymbol());
531  if (!Sm)
532    return false;
533  const DeclRegion *DeclReg = dyn_cast_or_null<DeclRegion>(Sm->getRegion());
534  if (!DeclReg)
535    return false;
536
537  // This region corresponds to a declaration, find out if it's a global/extern
538  // variable named stdin with the proper type.
539  if (const auto *D = dyn_cast_or_null<VarDecl>(DeclReg->getDecl())) {
540    D = D->getCanonicalDecl();
541    if ((D->getName().find("stdin") != StringRef::npos) && D->isExternC()) {
542      const auto *PtrTy = dyn_cast<PointerType>(D->getType().getTypePtr());
543      if (PtrTy && PtrTy->getPointeeType().getCanonicalType() ==
544                       C.getASTContext().getFILEType().getCanonicalType())
545        return true;
546    }
547  }
548  return false;
549}
550
551static bool getPrintfFormatArgumentNum(const CallExpr *CE,
552                                       const CheckerContext &C,
553                                       unsigned int &ArgNum) {
554  // Find if the function contains a format string argument.
555  // Handles: fprintf, printf, sprintf, snprintf, vfprintf, vprintf, vsprintf,
556  // vsnprintf, syslog, custom annotated functions.
557  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
558  if (!FDecl)
559    return false;
560  for (const auto *Format : FDecl->specific_attrs<FormatAttr>()) {
561    ArgNum = Format->getFormatIdx() - 1;
562    if ((Format->getType()->getName() == "printf") && CE->getNumArgs() > ArgNum)
563      return true;
564  }
565
566  // Or if a function is named setproctitle (this is a heuristic).
567  if (C.getCalleeName(CE).find("setproctitle") != StringRef::npos) {
568    ArgNum = 0;
569    return true;
570  }
571
572  return false;
573}
574
575bool GenericTaintChecker::generateReportIfTainted(const Expr *E,
576                                                  const char Msg[],
577                                                  CheckerContext &C) const {
578  assert(E);
579
580  // Check for taint.
581  ProgramStateRef State = C.getState();
582  Optional<SVal> PointedToSVal = getPointedToSVal(C, E);
583  SVal TaintedSVal;
584  if (PointedToSVal && isTainted(State, *PointedToSVal))
585    TaintedSVal = *PointedToSVal;
586  else if (isTainted(State, E, C.getLocationContext()))
587    TaintedSVal = C.getSVal(E);
588  else
589    return false;
590
591  // Generate diagnostic.
592  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
593    initBugType();
594    auto report = llvm::make_unique<BugReport>(*BT, Msg, N);
595    report->addRange(E->getSourceRange());
596    report->addVisitor(llvm::make_unique<TaintBugVisitor>(TaintedSVal));
597    C.emitReport(std::move(report));
598    return true;
599  }
600  return false;
601}
602
603bool GenericTaintChecker::checkUncontrolledFormatString(
604    const CallExpr *CE, CheckerContext &C) const {
605  // Check if the function contains a format string argument.
606  unsigned int ArgNum = 0;
607  if (!getPrintfFormatArgumentNum(CE, C, ArgNum))
608    return false;
609
610  // If either the format string content or the pointer itself are tainted,
611  // warn.
612  return generateReportIfTainted(CE->getArg(ArgNum),
613                                 MsgUncontrolledFormatString, C);
614}
615
616bool GenericTaintChecker::checkSystemCall(const CallExpr *CE, StringRef Name,
617                                          CheckerContext &C) const {
618  // TODO: It might make sense to run this check on demand. In some cases,
619  // we should check if the environment has been cleansed here. We also might
620  // need to know if the user was reset before these calls(seteuid).
621  unsigned ArgNum = llvm::StringSwitch<unsigned>(Name)
622                        .Case("system", 0)
623                        .Case("popen", 0)
624                        .Case("execl", 0)
625                        .Case("execle", 0)
626                        .Case("execlp", 0)
627                        .Case("execv", 0)
628                        .Case("execvp", 0)
629                        .Case("execvP", 0)
630                        .Case("execve", 0)
631                        .Case("dlopen", 0)
632                        .Default(UINT_MAX);
633
634  if (ArgNum == UINT_MAX || CE->getNumArgs() < (ArgNum + 1))
635    return false;
636
637  return generateReportIfTainted(CE->getArg(ArgNum), MsgSanitizeSystemArgs, C);
638}
639
640// TODO: Should this check be a part of the CString checker?
641// If yes, should taint be a global setting?
642bool GenericTaintChecker::checkTaintedBufferSize(const CallExpr *CE,
643                                                 const FunctionDecl *FDecl,
644                                                 CheckerContext &C) const {
645  // If the function has a buffer size argument, set ArgNum.
646  unsigned ArgNum = InvalidArgIndex;
647  unsigned BId = 0;
648  if ((BId = FDecl->getMemoryFunctionKind()))
649    switch (BId) {
650    case Builtin::BImemcpy:
651    case Builtin::BImemmove:
652    case Builtin::BIstrncpy:
653      ArgNum = 2;
654      break;
655    case Builtin::BIstrndup:
656      ArgNum = 1;
657      break;
658    default:
659      break;
660    };
661
662  if (ArgNum == InvalidArgIndex) {
663    if (C.isCLibraryFunction(FDecl, "malloc") ||
664        C.isCLibraryFunction(FDecl, "calloc") ||
665        C.isCLibraryFunction(FDecl, "alloca"))
666      ArgNum = 0;
667    else if (C.isCLibraryFunction(FDecl, "memccpy"))
668      ArgNum = 3;
669    else if (C.isCLibraryFunction(FDecl, "realloc"))
670      ArgNum = 1;
671    else if (C.isCLibraryFunction(FDecl, "bcopy"))
672      ArgNum = 2;
673  }
674
675  return ArgNum != InvalidArgIndex && CE->getNumArgs() > ArgNum &&
676         generateReportIfTainted(CE->getArg(ArgNum), MsgTaintedBufferSize, C);
677}
678
679void ento::registerGenericTaintChecker(CheckerManager &mgr) {
680  mgr.registerChecker<GenericTaintChecker>();
681}
682
683bool ento::shouldRegisterGenericTaintChecker(const LangOptions &LO) {
684  return true;
685}
686