clang  19.0.0git
CheckSecuritySyntaxOnly.cpp
Go to the documentation of this file.
1 //==- CheckSecuritySyntaxOnly.cpp - Basic security checks --------*- 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 file defines a set of flow-insensitive security checks.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "clang/AST/StmtVisitor.h"
16 #include "clang/Basic/TargetInfo.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/StringSwitch.h"
22 #include "llvm/Support/raw_ostream.h"
23 
24 using namespace clang;
25 using namespace ento;
26 
27 static bool isArc4RandomAvailable(const ASTContext &Ctx) {
28  const llvm::Triple &T = Ctx.getTargetInfo().getTriple();
29  return T.getVendor() == llvm::Triple::Apple ||
30  T.isOSFreeBSD() ||
31  T.isOSNetBSD() ||
32  T.isOSOpenBSD() ||
33  T.isOSDragonFly();
34 }
35 
36 namespace {
37 struct ChecksFilter {
38  bool check_bcmp = false;
39  bool check_bcopy = false;
40  bool check_bzero = false;
41  bool check_gets = false;
42  bool check_getpw = false;
43  bool check_mktemp = false;
44  bool check_mkstemp = false;
45  bool check_strcpy = false;
46  bool check_DeprecatedOrUnsafeBufferHandling = false;
47  bool check_rand = false;
48  bool check_vfork = false;
49  bool check_FloatLoopCounter = false;
50  bool check_UncheckedReturn = false;
51  bool check_decodeValueOfObjCType = false;
52 
53  CheckerNameRef checkName_bcmp;
54  CheckerNameRef checkName_bcopy;
55  CheckerNameRef checkName_bzero;
56  CheckerNameRef checkName_gets;
57  CheckerNameRef checkName_getpw;
58  CheckerNameRef checkName_mktemp;
59  CheckerNameRef checkName_mkstemp;
60  CheckerNameRef checkName_strcpy;
61  CheckerNameRef checkName_DeprecatedOrUnsafeBufferHandling;
62  CheckerNameRef checkName_rand;
63  CheckerNameRef checkName_vfork;
64  CheckerNameRef checkName_FloatLoopCounter;
65  CheckerNameRef checkName_UncheckedReturn;
66  CheckerNameRef checkName_decodeValueOfObjCType;
67 };
68 
69 class WalkAST : public StmtVisitor<WalkAST> {
70  BugReporter &BR;
72  enum { num_setids = 6 };
73  IdentifierInfo *II_setid[num_setids];
74 
75  const bool CheckRand;
76  const ChecksFilter &filter;
77 
78 public:
79  WalkAST(BugReporter &br, AnalysisDeclContext* ac,
80  const ChecksFilter &f)
81  : BR(br), AC(ac), II_setid(),
82  CheckRand(isArc4RandomAvailable(BR.getContext())),
83  filter(f) {}
84 
85  // Statement visitor methods.
86  void VisitCallExpr(CallExpr *CE);
87  void VisitObjCMessageExpr(ObjCMessageExpr *CE);
88  void VisitForStmt(ForStmt *S);
89  void VisitCompoundStmt (CompoundStmt *S);
90  void VisitStmt(Stmt *S) { VisitChildren(S); }
91 
92  void VisitChildren(Stmt *S);
93 
94  // Helpers.
95  bool checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD);
96 
97  typedef void (WalkAST::*FnCheck)(const CallExpr *, const FunctionDecl *);
98  typedef void (WalkAST::*MsgCheck)(const ObjCMessageExpr *);
99 
100  // Checker-specific methods.
101  void checkLoopConditionForFloat(const ForStmt *FS);
102  void checkCall_bcmp(const CallExpr *CE, const FunctionDecl *FD);
103  void checkCall_bcopy(const CallExpr *CE, const FunctionDecl *FD);
104  void checkCall_bzero(const CallExpr *CE, const FunctionDecl *FD);
105  void checkCall_gets(const CallExpr *CE, const FunctionDecl *FD);
106  void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
107  void checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD);
108  void checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD);
109  void checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD);
110  void checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD);
111  void checkDeprecatedOrUnsafeBufferHandling(const CallExpr *CE,
112  const FunctionDecl *FD);
113  void checkCall_rand(const CallExpr *CE, const FunctionDecl *FD);
114  void checkCall_random(const CallExpr *CE, const FunctionDecl *FD);
115  void checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD);
116  void checkMsg_decodeValueOfObjCType(const ObjCMessageExpr *ME);
117  void checkUncheckedReturnValue(CallExpr *CE);
118 };
119 } // end anonymous namespace
120 
121 //===----------------------------------------------------------------------===//
122 // AST walking.
123 //===----------------------------------------------------------------------===//
124 
125 void WalkAST::VisitChildren(Stmt *S) {
126  for (Stmt *Child : S->children())
127  if (Child)
128  Visit(Child);
129 }
130 
131 void WalkAST::VisitCallExpr(CallExpr *CE) {
132  // Get the callee.
133  const FunctionDecl *FD = CE->getDirectCallee();
134 
135  if (!FD)
136  return;
137 
138  // Get the name of the callee. If it's a builtin, strip off the prefix.
139  IdentifierInfo *II = FD->getIdentifier();
140  if (!II) // if no identifier, not a simple C function
141  return;
142  StringRef Name = II->getName();
143  Name.consume_front("__builtin_");
144 
145  // Set the evaluation function by switching on the callee name.
146  FnCheck evalFunction =
147  llvm::StringSwitch<FnCheck>(Name)
148  .Case("bcmp", &WalkAST::checkCall_bcmp)
149  .Case("bcopy", &WalkAST::checkCall_bcopy)
150  .Case("bzero", &WalkAST::checkCall_bzero)
151  .Case("gets", &WalkAST::checkCall_gets)
152  .Case("getpw", &WalkAST::checkCall_getpw)
153  .Case("mktemp", &WalkAST::checkCall_mktemp)
154  .Case("mkstemp", &WalkAST::checkCall_mkstemp)
155  .Case("mkdtemp", &WalkAST::checkCall_mkstemp)
156  .Case("mkstemps", &WalkAST::checkCall_mkstemp)
157  .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
158  .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
159  .Cases("sprintf", "vsprintf", "scanf", "wscanf", "fscanf", "fwscanf",
160  "vscanf", "vwscanf", "vfscanf", "vfwscanf",
161  &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
162  .Cases("sscanf", "swscanf", "vsscanf", "vswscanf", "swprintf",
163  "snprintf", "vswprintf", "vsnprintf", "memcpy", "memmove",
164  &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
165  .Cases("strncpy", "strncat", "memset", "fprintf",
166  &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
167  .Case("drand48", &WalkAST::checkCall_rand)
168  .Case("erand48", &WalkAST::checkCall_rand)
169  .Case("jrand48", &WalkAST::checkCall_rand)
170  .Case("lrand48", &WalkAST::checkCall_rand)
171  .Case("mrand48", &WalkAST::checkCall_rand)
172  .Case("nrand48", &WalkAST::checkCall_rand)
173  .Case("lcong48", &WalkAST::checkCall_rand)
174  .Case("rand", &WalkAST::checkCall_rand)
175  .Case("rand_r", &WalkAST::checkCall_rand)
176  .Case("random", &WalkAST::checkCall_random)
177  .Case("vfork", &WalkAST::checkCall_vfork)
178  .Default(nullptr);
179 
180  // If the callee isn't defined, it is not of security concern.
181  // Check and evaluate the call.
182  if (evalFunction)
183  (this->*evalFunction)(CE, FD);
184 
185  // Recurse and check children.
186  VisitChildren(CE);
187 }
188 
189 void WalkAST::VisitObjCMessageExpr(ObjCMessageExpr *ME) {
190  MsgCheck evalFunction =
191  llvm::StringSwitch<MsgCheck>(ME->getSelector().getAsString())
192  .Case("decodeValueOfObjCType:at:",
193  &WalkAST::checkMsg_decodeValueOfObjCType)
194  .Default(nullptr);
195 
196  if (evalFunction)
197  (this->*evalFunction)(ME);
198 
199  // Recurse and check children.
200  VisitChildren(ME);
201 }
202 
203 void WalkAST::VisitCompoundStmt(CompoundStmt *S) {
204  for (Stmt *Child : S->children())
205  if (Child) {
206  if (CallExpr *CE = dyn_cast<CallExpr>(Child))
207  checkUncheckedReturnValue(CE);
208  Visit(Child);
209  }
210 }
211 
212 void WalkAST::VisitForStmt(ForStmt *FS) {
213  checkLoopConditionForFloat(FS);
214 
215  // Recurse and check children.
216  VisitChildren(FS);
217 }
218 
219 //===----------------------------------------------------------------------===//
220 // Check: floating point variable used as loop counter.
221 // Implements: CERT security coding advisory FLP-30.
222 //===----------------------------------------------------------------------===//
223 
224 // Returns either 'x' or 'y', depending on which one of them is incremented
225 // in 'expr', or nullptr if none of them is incremented.
226 static const DeclRefExpr*
227 getIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
228  expr = expr->IgnoreParenCasts();
229 
230  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
231  if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
232  B->getOpcode() == BO_Comma))
233  return nullptr;
234 
235  if (const DeclRefExpr *lhs = getIncrementedVar(B->getLHS(), x, y))
236  return lhs;
237 
238  if (const DeclRefExpr *rhs = getIncrementedVar(B->getRHS(), x, y))
239  return rhs;
240 
241  return nullptr;
242  }
243 
244  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(expr)) {
245  const NamedDecl *ND = DR->getDecl();
246  return ND == x || ND == y ? DR : nullptr;
247  }
248 
249  if (const UnaryOperator *U = dyn_cast<UnaryOperator>(expr))
250  return U->isIncrementDecrementOp()
251  ? getIncrementedVar(U->getSubExpr(), x, y) : nullptr;
252 
253  return nullptr;
254 }
255 
256 /// CheckLoopConditionForFloat - This check looks for 'for' statements that
257 /// use a floating point variable as a loop counter.
258 /// CERT: FLP30-C, FLP30-CPP.
259 ///
260 void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) {
261  if (!filter.check_FloatLoopCounter)
262  return;
263 
264  // Does the loop have a condition?
265  const Expr *condition = FS->getCond();
266 
267  if (!condition)
268  return;
269 
270  // Does the loop have an increment?
271  const Expr *increment = FS->getInc();
272 
273  if (!increment)
274  return;
275 
276  // Strip away '()' and casts.
277  condition = condition->IgnoreParenCasts();
278  increment = increment->IgnoreParenCasts();
279 
280  // Is the loop condition a comparison?
281  const BinaryOperator *B = dyn_cast<BinaryOperator>(condition);
282 
283  if (!B)
284  return;
285 
286  // Is this a comparison?
287  if (!(B->isRelationalOp() || B->isEqualityOp()))
288  return;
289 
290  // Are we comparing variables?
291  const DeclRefExpr *drLHS =
292  dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenLValueCasts());
293  const DeclRefExpr *drRHS =
294  dyn_cast<DeclRefExpr>(B->getRHS()->IgnoreParenLValueCasts());
295 
296  // Does at least one of the variables have a floating point type?
297  drLHS = drLHS && drLHS->getType()->isRealFloatingType() ? drLHS : nullptr;
298  drRHS = drRHS && drRHS->getType()->isRealFloatingType() ? drRHS : nullptr;
299 
300  if (!drLHS && !drRHS)
301  return;
302 
303  const VarDecl *vdLHS = drLHS ? dyn_cast<VarDecl>(drLHS->getDecl()) : nullptr;
304  const VarDecl *vdRHS = drRHS ? dyn_cast<VarDecl>(drRHS->getDecl()) : nullptr;
305 
306  if (!vdLHS && !vdRHS)
307  return;
308 
309  // Does either variable appear in increment?
310  const DeclRefExpr *drInc = getIncrementedVar(increment, vdLHS, vdRHS);
311  if (!drInc)
312  return;
313 
314  const VarDecl *vdInc = cast<VarDecl>(drInc->getDecl());
315  assert(vdInc && (vdInc == vdLHS || vdInc == vdRHS));
316 
317  // Emit the error. First figure out which DeclRefExpr in the condition
318  // referenced the compared variable.
319  const DeclRefExpr *drCond = vdLHS == vdInc ? drLHS : drRHS;
320 
322  SmallString<256> sbuf;
323  llvm::raw_svector_ostream os(sbuf);
324 
325  os << "Variable '" << drCond->getDecl()->getName()
326  << "' with floating point type '" << drCond->getType()
327  << "' should not be used as a loop counter";
328 
329  ranges.push_back(drCond->getSourceRange());
330  ranges.push_back(drInc->getSourceRange());
331 
332  const char *bugType = "Floating point variable used as loop counter";
333 
334  PathDiagnosticLocation FSLoc =
335  PathDiagnosticLocation::createBegin(FS, BR.getSourceManager(), AC);
336  BR.EmitBasicReport(AC->getDecl(), filter.checkName_FloatLoopCounter,
337  bugType, "Security", os.str(),
338  FSLoc, ranges);
339 }
340 
341 //===----------------------------------------------------------------------===//
342 // Check: Any use of bcmp.
343 // CWE-477: Use of Obsolete Functions
344 // bcmp was deprecated in POSIX.1-2008
345 //===----------------------------------------------------------------------===//
346 
347 void WalkAST::checkCall_bcmp(const CallExpr *CE, const FunctionDecl *FD) {
348  if (!filter.check_bcmp)
349  return;
350 
351  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
352  if (!FPT)
353  return;
354 
355  // Verify that the function takes three arguments.
356  if (FPT->getNumParams() != 3)
357  return;
358 
359  for (int i = 0; i < 2; i++) {
360  // Verify the first and second argument type is void*.
361  const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
362  if (!PT)
363  return;
364 
365  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
366  return;
367  }
368 
369  // Verify the third argument type is integer.
371  return;
372 
373  // Issue a warning.
374  PathDiagnosticLocation CELoc =
375  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
376  BR.EmitBasicReport(AC->getDecl(), filter.checkName_bcmp,
377  "Use of deprecated function in call to 'bcmp()'",
378  "Security",
379  "The bcmp() function is obsoleted by memcmp().",
380  CELoc, CE->getCallee()->getSourceRange());
381 }
382 
383 //===----------------------------------------------------------------------===//
384 // Check: Any use of bcopy.
385 // CWE-477: Use of Obsolete Functions
386 // bcopy was deprecated in POSIX.1-2008
387 //===----------------------------------------------------------------------===//
388 
389 void WalkAST::checkCall_bcopy(const CallExpr *CE, const FunctionDecl *FD) {
390  if (!filter.check_bcopy)
391  return;
392 
393  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
394  if (!FPT)
395  return;
396 
397  // Verify that the function takes three arguments.
398  if (FPT->getNumParams() != 3)
399  return;
400 
401  for (int i = 0; i < 2; i++) {
402  // Verify the first and second argument type is void*.
403  const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
404  if (!PT)
405  return;
406 
407  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
408  return;
409  }
410 
411  // Verify the third argument type is integer.
413  return;
414 
415  // Issue a warning.
416  PathDiagnosticLocation CELoc =
417  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
418  BR.EmitBasicReport(AC->getDecl(), filter.checkName_bcopy,
419  "Use of deprecated function in call to 'bcopy()'",
420  "Security",
421  "The bcopy() function is obsoleted by memcpy() "
422  "or memmove().",
423  CELoc, CE->getCallee()->getSourceRange());
424 }
425 
426 //===----------------------------------------------------------------------===//
427 // Check: Any use of bzero.
428 // CWE-477: Use of Obsolete Functions
429 // bzero was deprecated in POSIX.1-2008
430 //===----------------------------------------------------------------------===//
431 
432 void WalkAST::checkCall_bzero(const CallExpr *CE, const FunctionDecl *FD) {
433  if (!filter.check_bzero)
434  return;
435 
436  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
437  if (!FPT)
438  return;
439 
440  // Verify that the function takes two arguments.
441  if (FPT->getNumParams() != 2)
442  return;
443 
444  // Verify the first argument type is void*.
445  const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>();
446  if (!PT)
447  return;
448 
449  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
450  return;
451 
452  // Verify the second argument type is integer.
454  return;
455 
456  // Issue a warning.
457  PathDiagnosticLocation CELoc =
458  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
459  BR.EmitBasicReport(AC->getDecl(), filter.checkName_bzero,
460  "Use of deprecated function in call to 'bzero()'",
461  "Security",
462  "The bzero() function is obsoleted by memset().",
463  CELoc, CE->getCallee()->getSourceRange());
464 }
465 
466 
467 //===----------------------------------------------------------------------===//
468 // Check: Any use of 'gets' is insecure. Most man pages literally says this.
469 //
470 // Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
471 // CWE-242: Use of Inherently Dangerous Function
472 //===----------------------------------------------------------------------===//
473 
474 void WalkAST::checkCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
475  if (!filter.check_gets)
476  return;
477 
478  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
479  if (!FPT)
480  return;
481 
482  // Verify that the function takes a single argument.
483  if (FPT->getNumParams() != 1)
484  return;
485 
486  // Is the argument a 'char*'?
487  const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>();
488  if (!PT)
489  return;
490 
491  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
492  return;
493 
494  // Issue a warning.
495  PathDiagnosticLocation CELoc =
496  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
497  BR.EmitBasicReport(AC->getDecl(), filter.checkName_gets,
498  "Potential buffer overflow in call to 'gets'",
499  "Security",
500  "Call to function 'gets' is extremely insecure as it can "
501  "always result in a buffer overflow",
502  CELoc, CE->getCallee()->getSourceRange());
503 }
504 
505 //===----------------------------------------------------------------------===//
506 // Check: Any use of 'getpwd' is insecure.
507 // CWE-477: Use of Obsolete Functions
508 //===----------------------------------------------------------------------===//
509 
510 void WalkAST::checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD) {
511  if (!filter.check_getpw)
512  return;
513 
514  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
515  if (!FPT)
516  return;
517 
518  // Verify that the function takes two arguments.
519  if (FPT->getNumParams() != 2)
520  return;
521 
522  // Verify the first argument type is integer.
524  return;
525 
526  // Verify the second argument type is char*.
527  const PointerType *PT = FPT->getParamType(1)->getAs<PointerType>();
528  if (!PT)
529  return;
530 
531  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
532  return;
533 
534  // Issue a warning.
535  PathDiagnosticLocation CELoc =
536  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
537  BR.EmitBasicReport(AC->getDecl(), filter.checkName_getpw,
538  "Potential buffer overflow in call to 'getpw'",
539  "Security",
540  "The getpw() function is dangerous as it may overflow the "
541  "provided buffer. It is obsoleted by getpwuid().",
542  CELoc, CE->getCallee()->getSourceRange());
543 }
544 
545 //===----------------------------------------------------------------------===//
546 // Check: Any use of 'mktemp' is insecure. It is obsoleted by mkstemp().
547 // CWE-377: Insecure Temporary File
548 //===----------------------------------------------------------------------===//
549 
550 void WalkAST::checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
551  if (!filter.check_mktemp) {
552  // Fall back to the security check of looking for enough 'X's in the
553  // format string, since that is a less severe warning.
554  checkCall_mkstemp(CE, FD);
555  return;
556  }
557 
558  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
559  if(!FPT)
560  return;
561 
562  // Verify that the function takes a single argument.
563  if (FPT->getNumParams() != 1)
564  return;
565 
566  // Verify that the argument is Pointer Type.
567  const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>();
568  if (!PT)
569  return;
570 
571  // Verify that the argument is a 'char*'.
572  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
573  return;
574 
575  // Issue a warning.
576  PathDiagnosticLocation CELoc =
577  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
578  BR.EmitBasicReport(AC->getDecl(), filter.checkName_mktemp,
579  "Potential insecure temporary file in call 'mktemp'",
580  "Security",
581  "Call to function 'mktemp' is insecure as it always "
582  "creates or uses insecure temporary file. Use 'mkstemp' "
583  "instead",
584  CELoc, CE->getCallee()->getSourceRange());
585 }
586 
587 //===----------------------------------------------------------------------===//
588 // Check: Use of 'mkstemp', 'mktemp', 'mkdtemp' should contain at least 6 X's.
589 //===----------------------------------------------------------------------===//
590 
591 void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
592  if (!filter.check_mkstemp)
593  return;
594 
595  StringRef Name = FD->getIdentifier()->getName();
596  std::pair<signed, signed> ArgSuffix =
597  llvm::StringSwitch<std::pair<signed, signed> >(Name)
598  .Case("mktemp", std::make_pair(0,-1))
599  .Case("mkstemp", std::make_pair(0,-1))
600  .Case("mkdtemp", std::make_pair(0,-1))
601  .Case("mkstemps", std::make_pair(0,1))
602  .Default(std::make_pair(-1, -1));
603 
604  assert(ArgSuffix.first >= 0 && "Unsupported function");
605 
606  // Check if the number of arguments is consistent with out expectations.
607  unsigned numArgs = CE->getNumArgs();
608  if ((signed) numArgs <= ArgSuffix.first)
609  return;
610 
611  const StringLiteral *strArg =
612  dyn_cast<StringLiteral>(CE->getArg((unsigned)ArgSuffix.first)
613  ->IgnoreParenImpCasts());
614 
615  // Currently we only handle string literals. It is possible to do better,
616  // either by looking at references to const variables, or by doing real
617  // flow analysis.
618  if (!strArg || strArg->getCharByteWidth() != 1)
619  return;
620 
621  // Count the number of X's, taking into account a possible cutoff suffix.
622  StringRef str = strArg->getString();
623  unsigned numX = 0;
624  unsigned n = str.size();
625 
626  // Take into account the suffix.
627  unsigned suffix = 0;
628  if (ArgSuffix.second >= 0) {
629  const Expr *suffixEx = CE->getArg((unsigned)ArgSuffix.second);
630  Expr::EvalResult EVResult;
631  if (!suffixEx->EvaluateAsInt(EVResult, BR.getContext()))
632  return;
633  llvm::APSInt Result = EVResult.Val.getInt();
634  // FIXME: Issue a warning.
635  if (Result.isNegative())
636  return;
637  suffix = (unsigned) Result.getZExtValue();
638  n = (n > suffix) ? n - suffix : 0;
639  }
640 
641  for (unsigned i = 0; i < n; ++i)
642  if (str[i] == 'X') ++numX;
643 
644  if (numX >= 6)
645  return;
646 
647  // Issue a warning.
648  PathDiagnosticLocation CELoc =
649  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
650  SmallString<512> buf;
651  llvm::raw_svector_ostream out(buf);
652  out << "Call to '" << Name << "' should have at least 6 'X's in the"
653  " format string to be secure (" << numX << " 'X'";
654  if (numX != 1)
655  out << 's';
656  out << " seen";
657  if (suffix) {
658  out << ", " << suffix << " character";
659  if (suffix > 1)
660  out << 's';
661  out << " used as a suffix";
662  }
663  out << ')';
664  BR.EmitBasicReport(AC->getDecl(), filter.checkName_mkstemp,
665  "Insecure temporary file creation", "Security",
666  out.str(), CELoc, strArg->getSourceRange());
667 }
668 
669 //===----------------------------------------------------------------------===//
670 // Check: Any use of 'strcpy' is insecure.
671 //
672 // CWE-119: Improper Restriction of Operations within
673 // the Bounds of a Memory Buffer
674 //===----------------------------------------------------------------------===//
675 
676 void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
677  if (!filter.check_strcpy)
678  return;
679 
680  if (!checkCall_strCommon(CE, FD))
681  return;
682 
683  const auto *Target = CE->getArg(0)->IgnoreImpCasts(),
684  *Source = CE->getArg(1)->IgnoreImpCasts();
685 
686  if (const auto *Array = dyn_cast<ConstantArrayType>(Target->getType())) {
687  uint64_t ArraySize = BR.getContext().getTypeSize(Array) / 8;
688  if (const auto *String = dyn_cast<StringLiteral>(Source)) {
689  if (ArraySize >= String->getLength() + 1)
690  return;
691  }
692  }
693 
694  // Issue a warning.
695  PathDiagnosticLocation CELoc =
696  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
697  BR.EmitBasicReport(AC->getDecl(), filter.checkName_strcpy,
698  "Potential insecure memory buffer bounds restriction in "
699  "call 'strcpy'",
700  "Security",
701  "Call to function 'strcpy' is insecure as it does not "
702  "provide bounding of the memory buffer. Replace "
703  "unbounded copy functions with analogous functions that "
704  "support length arguments such as 'strlcpy'. CWE-119.",
705  CELoc, CE->getCallee()->getSourceRange());
706 }
707 
708 //===----------------------------------------------------------------------===//
709 // Check: Any use of 'strcat' is insecure.
710 //
711 // CWE-119: Improper Restriction of Operations within
712 // the Bounds of a Memory Buffer
713 //===----------------------------------------------------------------------===//
714 
715 void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) {
716  if (!filter.check_strcpy)
717  return;
718 
719  if (!checkCall_strCommon(CE, FD))
720  return;
721 
722  // Issue a warning.
723  PathDiagnosticLocation CELoc =
724  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
725  BR.EmitBasicReport(AC->getDecl(), filter.checkName_strcpy,
726  "Potential insecure memory buffer bounds restriction in "
727  "call 'strcat'",
728  "Security",
729  "Call to function 'strcat' is insecure as it does not "
730  "provide bounding of the memory buffer. Replace "
731  "unbounded copy functions with analogous functions that "
732  "support length arguments such as 'strlcat'. CWE-119.",
733  CELoc, CE->getCallee()->getSourceRange());
734 }
735 
736 //===----------------------------------------------------------------------===//
737 // Check: Any use of 'sprintf', 'vsprintf', 'scanf', 'wscanf', 'fscanf',
738 // 'fwscanf', 'vscanf', 'vwscanf', 'vfscanf', 'vfwscanf', 'sscanf',
739 // 'swscanf', 'vsscanf', 'vswscanf', 'swprintf', 'snprintf', 'vswprintf',
740 // 'vsnprintf', 'memcpy', 'memmove', 'strncpy', 'strncat', 'memset',
741 // 'fprintf' is deprecated since C11.
742 //
743 // Use of 'sprintf', 'fprintf', 'vsprintf', 'scanf', 'wscanf', 'fscanf',
744 // 'fwscanf', 'vscanf', 'vwscanf', 'vfscanf', 'vfwscanf', 'sscanf',
745 // 'swscanf', 'vsscanf', 'vswscanf' without buffer limitations
746 // is insecure.
747 //
748 // CWE-119: Improper Restriction of Operations within
749 // the Bounds of a Memory Buffer
750 //===----------------------------------------------------------------------===//
751 
752 void WalkAST::checkDeprecatedOrUnsafeBufferHandling(const CallExpr *CE,
753  const FunctionDecl *FD) {
754  if (!filter.check_DeprecatedOrUnsafeBufferHandling)
755  return;
756 
757  if (!BR.getContext().getLangOpts().C11)
758  return;
759 
760  // Issue a warning. ArgIndex == -1: Deprecated but not unsafe (has size
761  // restrictions).
762  enum { DEPR_ONLY = -1, UNKNOWN_CALL = -2 };
763 
764  StringRef Name = FD->getIdentifier()->getName();
765  Name.consume_front("__builtin_");
766 
767  int ArgIndex =
768  llvm::StringSwitch<int>(Name)
769  .Cases("scanf", "wscanf", "vscanf", "vwscanf", 0)
770  .Cases("fscanf", "fwscanf", "vfscanf", "vfwscanf", "sscanf",
771  "swscanf", "vsscanf", "vswscanf", 1)
772  .Cases("sprintf", "vsprintf", "fprintf", 1)
773  .Cases("swprintf", "snprintf", "vswprintf", "vsnprintf", "memcpy",
774  "memmove", "memset", "strncpy", "strncat", DEPR_ONLY)
775  .Default(UNKNOWN_CALL);
776 
777  assert(ArgIndex != UNKNOWN_CALL && "Unsupported function");
778  bool BoundsProvided = ArgIndex == DEPR_ONLY;
779 
780  if (!BoundsProvided) {
781  // Currently we only handle (not wide) string literals. It is possible to do
782  // better, either by looking at references to const variables, or by doing
783  // real flow analysis.
784  auto FormatString =
785  dyn_cast<StringLiteral>(CE->getArg(ArgIndex)->IgnoreParenImpCasts());
786  if (FormatString && !FormatString->getString().contains("%s") &&
787  !FormatString->getString().contains("%["))
788  BoundsProvided = true;
789  }
790 
791  SmallString<128> Buf1;
792  SmallString<512> Buf2;
793  llvm::raw_svector_ostream Out1(Buf1);
794  llvm::raw_svector_ostream Out2(Buf2);
795 
796  Out1 << "Potential insecure memory buffer bounds restriction in call '"
797  << Name << "'";
798  Out2 << "Call to function '" << Name
799  << "' is insecure as it does not provide ";
800 
801  if (!BoundsProvided) {
802  Out2 << "bounding of the memory buffer or ";
803  }
804 
805  Out2 << "security checks introduced "
806  "in the C11 standard. Replace with analogous functions that "
807  "support length arguments or provides boundary checks such as '"
808  << Name << "_s' in case of C11";
809 
810  PathDiagnosticLocation CELoc =
811  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
812  BR.EmitBasicReport(AC->getDecl(),
813  filter.checkName_DeprecatedOrUnsafeBufferHandling,
814  Out1.str(), "Security", Out2.str(), CELoc,
815  CE->getCallee()->getSourceRange());
816 }
817 
818 //===----------------------------------------------------------------------===//
819 // Common check for str* functions with no bounds parameters.
820 //===----------------------------------------------------------------------===//
821 
822 bool WalkAST::checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD) {
823  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
824  if (!FPT)
825  return false;
826 
827  // Verify the function takes two arguments, three in the _chk version.
828  int numArgs = FPT->getNumParams();
829  if (numArgs != 2 && numArgs != 3)
830  return false;
831 
832  // Verify the type for both arguments.
833  for (int i = 0; i < 2; i++) {
834  // Verify that the arguments are pointers.
835  const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
836  if (!PT)
837  return false;
838 
839  // Verify that the argument is a 'char*'.
840  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
841  return false;
842  }
843 
844  return true;
845 }
846 
847 //===----------------------------------------------------------------------===//
848 // Check: Linear congruent random number generators should not be used,
849 // i.e. rand(), random().
850 //
851 // E. Bach, "Efficient prediction of Marsaglia-Zaman random number generators,"
852 // in IEEE Transactions on Information Theory, vol. 44, no. 3, pp. 1253-1257,
853 // May 1998, https://doi.org/10.1109/18.669305
854 //
855 // CWE-338: Use of cryptographically weak prng
856 //===----------------------------------------------------------------------===//
857 
858 void WalkAST::checkCall_rand(const CallExpr *CE, const FunctionDecl *FD) {
859  if (!filter.check_rand || !CheckRand)
860  return;
861 
862  const FunctionProtoType *FTP = FD->getType()->getAs<FunctionProtoType>();
863  if (!FTP)
864  return;
865 
866  if (FTP->getNumParams() == 1) {
867  // Is the argument an 'unsigned short *'?
868  // (Actually any integer type is allowed.)
869  const PointerType *PT = FTP->getParamType(0)->getAs<PointerType>();
870  if (!PT)
871  return;
872 
874  return;
875  } else if (FTP->getNumParams() != 0)
876  return;
877 
878  // Issue a warning.
879  SmallString<256> buf1;
880  llvm::raw_svector_ostream os1(buf1);
881  os1 << '\'' << *FD << "' is a poor random number generator";
882 
883  SmallString<256> buf2;
884  llvm::raw_svector_ostream os2(buf2);
885  os2 << "Function '" << *FD
886  << "' is obsolete because it implements a poor random number generator."
887  << " Use 'arc4random' instead";
888 
889  PathDiagnosticLocation CELoc =
890  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
891  BR.EmitBasicReport(AC->getDecl(), filter.checkName_rand, os1.str(),
892  "Security", os2.str(), CELoc,
893  CE->getCallee()->getSourceRange());
894 }
895 
896 // See justification for rand().
897 void WalkAST::checkCall_random(const CallExpr *CE, const FunctionDecl *FD) {
898  if (!CheckRand || !filter.check_rand)
899  return;
900 
901  const FunctionProtoType *FTP = FD->getType()->getAs<FunctionProtoType>();
902  if (!FTP)
903  return;
904 
905  // Verify that the function takes no argument.
906  if (FTP->getNumParams() != 0)
907  return;
908 
909  // Issue a warning.
910  PathDiagnosticLocation CELoc =
911  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
912  BR.EmitBasicReport(AC->getDecl(), filter.checkName_rand,
913  "'random' is not a secure random number generator",
914  "Security",
915  "The 'random' function produces a sequence of values that "
916  "an adversary may be able to predict. Use 'arc4random' "
917  "instead", CELoc, CE->getCallee()->getSourceRange());
918 }
919 
920 //===----------------------------------------------------------------------===//
921 // Check: 'vfork' should not be used.
922 // POS33-C: Do not use vfork().
923 //===----------------------------------------------------------------------===//
924 
925 void WalkAST::checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD) {
926  if (!filter.check_vfork)
927  return;
928 
929  // All calls to vfork() are insecure, issue a warning.
930  PathDiagnosticLocation CELoc =
931  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
932  BR.EmitBasicReport(AC->getDecl(), filter.checkName_vfork,
933  "Potential insecure implementation-specific behavior in "
934  "call 'vfork'",
935  "Security",
936  "Call to function 'vfork' is insecure as it can lead to "
937  "denial of service situations in the parent process. "
938  "Replace calls to vfork with calls to the safer "
939  "'posix_spawn' function",
940  CELoc, CE->getCallee()->getSourceRange());
941 }
942 
943 //===----------------------------------------------------------------------===//
944 // Check: '-decodeValueOfObjCType:at:' should not be used.
945 // It is deprecated in favor of '-decodeValueOfObjCType:at:size:' due to
946 // likelihood of buffer overflows.
947 //===----------------------------------------------------------------------===//
948 
949 void WalkAST::checkMsg_decodeValueOfObjCType(const ObjCMessageExpr *ME) {
950  if (!filter.check_decodeValueOfObjCType)
951  return;
952 
953  // Check availability of the secure alternative:
954  // iOS 11+, macOS 10.13+, tvOS 11+, and watchOS 4.0+
955  // FIXME: We probably shouldn't register the check if it's not available.
956  const TargetInfo &TI = AC->getASTContext().getTargetInfo();
957  const llvm::Triple &T = TI.getTriple();
958  const VersionTuple &VT = TI.getPlatformMinVersion();
959  switch (T.getOS()) {
960  case llvm::Triple::IOS:
961  if (VT < VersionTuple(11, 0))
962  return;
963  break;
964  case llvm::Triple::MacOSX:
965  if (VT < VersionTuple(10, 13))
966  return;
967  break;
968  case llvm::Triple::WatchOS:
969  if (VT < VersionTuple(4, 0))
970  return;
971  break;
972  case llvm::Triple::TvOS:
973  if (VT < VersionTuple(11, 0))
974  return;
975  break;
976  case llvm::Triple::XROS:
977  break;
978  default:
979  return;
980  }
981 
982  PathDiagnosticLocation MELoc =
983  PathDiagnosticLocation::createBegin(ME, BR.getSourceManager(), AC);
984  BR.EmitBasicReport(
985  AC->getDecl(), filter.checkName_decodeValueOfObjCType,
986  "Potential buffer overflow in '-decodeValueOfObjCType:at:'", "Security",
987  "Deprecated method '-decodeValueOfObjCType:at:' is insecure "
988  "as it can lead to potential buffer overflows. Use the safer "
989  "'-decodeValueOfObjCType:at:size:' method.",
990  MELoc, ME->getSourceRange());
991 }
992 
993 //===----------------------------------------------------------------------===//
994 // Check: The caller should always verify that the privileges
995 // were dropped successfully.
996 //
997 // Some library functions, like setuid() and setgid(), should always be used
998 // with a check of the return value to verify that the function completed
999 // successfully. If the drop fails, the software will continue to run
1000 // with the raised privileges, which might provide additional access
1001 // to unprivileged users.
1002 //
1003 // (Note that this check predates __attribute__((warn_unused_result)).
1004 // Do we still need it now that we have a compiler warning for this?
1005 // Are these standard functions already annotated this way?)
1006 //===----------------------------------------------------------------------===//
1007 
1008 void WalkAST::checkUncheckedReturnValue(CallExpr *CE) {
1009  if (!filter.check_UncheckedReturn)
1010  return;
1011 
1012  const FunctionDecl *FD = CE->getDirectCallee();
1013  if (!FD)
1014  return;
1015 
1016  if (II_setid[0] == nullptr) {
1017  static const char * const identifiers[num_setids] = {
1018  "setuid", "setgid", "seteuid", "setegid",
1019  "setreuid", "setregid"
1020  };
1021 
1022  for (size_t i = 0; i < num_setids; i++)
1023  II_setid[i] = &BR.getContext().Idents.get(identifiers[i]);
1024  }
1025 
1026  const IdentifierInfo *id = FD->getIdentifier();
1027  size_t identifierid;
1028 
1029  for (identifierid = 0; identifierid < num_setids; identifierid++)
1030  if (id == II_setid[identifierid])
1031  break;
1032 
1033  if (identifierid >= num_setids)
1034  return;
1035 
1036  const FunctionProtoType *FTP = FD->getType()->getAs<FunctionProtoType>();
1037  if (!FTP)
1038  return;
1039 
1040  // Verify that the function takes one or two arguments (depending on
1041  // the function).
1042  if (FTP->getNumParams() != (identifierid < 4 ? 1 : 2))
1043  return;
1044 
1045  // The arguments must be integers.
1046  for (unsigned i = 0; i < FTP->getNumParams(); i++)
1048  return;
1049 
1050  // Issue a warning.
1051  SmallString<256> buf1;
1052  llvm::raw_svector_ostream os1(buf1);
1053  os1 << "Return value is not checked in call to '" << *FD << '\'';
1054 
1055  SmallString<256> buf2;
1056  llvm::raw_svector_ostream os2(buf2);
1057  os2 << "The return value from the call to '" << *FD
1058  << "' is not checked. If an error occurs in '" << *FD
1059  << "', the following code may execute with unexpected privileges";
1060 
1061  PathDiagnosticLocation CELoc =
1062  PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
1063  BR.EmitBasicReport(AC->getDecl(), filter.checkName_UncheckedReturn, os1.str(),
1064  "Security", os2.str(), CELoc,
1065  CE->getCallee()->getSourceRange());
1066 }
1067 
1068 //===----------------------------------------------------------------------===//
1069 // SecuritySyntaxChecker
1070 //===----------------------------------------------------------------------===//
1071 
1072 namespace {
1073 class SecuritySyntaxChecker : public Checker<check::ASTCodeBody> {
1074 public:
1075  ChecksFilter filter;
1076 
1077  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
1078  BugReporter &BR) const {
1079  WalkAST walker(BR, mgr.getAnalysisDeclContext(D), filter);
1080  walker.Visit(D->getBody());
1081  }
1082 };
1083 }
1084 
1085 void ento::registerSecuritySyntaxChecker(CheckerManager &mgr) {
1086  mgr.registerChecker<SecuritySyntaxChecker>();
1087 }
1088 
1089 bool ento::shouldRegisterSecuritySyntaxChecker(const CheckerManager &mgr) {
1090  return true;
1091 }
1092 
1093 #define REGISTER_CHECKER(name) \
1094  void ento::register##name(CheckerManager &mgr) { \
1095  SecuritySyntaxChecker *checker = mgr.getChecker<SecuritySyntaxChecker>(); \
1096  checker->filter.check_##name = true; \
1097  checker->filter.checkName_##name = mgr.getCurrentCheckerName(); \
1098  } \
1099  \
1100  bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
1101 
1102 REGISTER_CHECKER(bcmp)
1103 REGISTER_CHECKER(bcopy)
1104 REGISTER_CHECKER(bzero)
1105 REGISTER_CHECKER(gets)
1106 REGISTER_CHECKER(getpw)
1107 REGISTER_CHECKER(mkstemp)
1108 REGISTER_CHECKER(mktemp)
1109 REGISTER_CHECKER(strcpy)
1110 REGISTER_CHECKER(rand)
1111 REGISTER_CHECKER(vfork)
1112 REGISTER_CHECKER(FloatLoopCounter)
1113 REGISTER_CHECKER(UncheckedReturn)
1114 REGISTER_CHECKER(DeprecatedOrUnsafeBufferHandling)
1115 REGISTER_CHECKER(decodeValueOfObjCType)
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
llvm::APSInt APSInt
#define REGISTER_CHECKER(name)
static const DeclRefExpr * getIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y)
static bool isArc4RandomAvailable(const ASTContext &Ctx)
llvm::MachO::Target Target
Definition: MachO.h:50
APSInt & getInt()
Definition: APValue.h:423
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:185
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:760
AnalysisDeclContext contains the context data for the function, method or block under analysis.
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3892
static bool isRelationalOp(Opcode Opc)
Definition: Expr.h:3985
Expr * getRHS() const
Definition: Expr.h:3943
static bool isEqualityOp(Opcode Opc)
Definition: Expr.h:3988
Expr * getLHS() const
Definition: Expr.h:3941
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2872
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3050
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3063
Expr * getCallee()
Definition: Expr.h:3022
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3042
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1606
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1260
ValueDecl * getDecl()
Definition: Expr.h:1328
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition: DeclBase.h:1077
This represents one expression.
Definition: Expr.h:110
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3116
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition: Expr.cpp:3128
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3111
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3091
QualType getType() const
Definition: Expr.h:142
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2781
Represents a function declaration or definition.
Definition: Decl.h:1972
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4668
unsigned getNumParams() const
Definition: Type.h:4901
QualType getParamType(unsigned i) const
Definition: Type.h:4903
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
This represents a decl that may have a name.
Definition: Decl.h:249
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:945
Selector getSelector() const
Definition: ExprObjC.cpp:293
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3151
QualType getPointeeType() const
Definition: Type.h:3161
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7465
std::string getAsString() const
Derive the full selector name (e.g.
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:185
Stmt - This represents one statement.
Definition: Stmt.h:84
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1773
StringRef getString() const
Definition: Expr.h:1850
unsigned getCharByteWidth() const
Definition: Expr.h:1891
Exposes information about the current target.
Definition: TargetInfo.h:218
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
Definition: TargetInfo.h:1648
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1256
bool isIntegralOrUnscopedEnumerationType() const
Determine whether this type is an integral or unscoped enumeration type.
Definition: Type.cpp:2070
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2265
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8160
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2235
QualType getType() const
Definition: Decl.h:718
Represents a variable declaration or definition.
Definition: Decl.h:919
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:585
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
Defines the clang::TargetInfo interface.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
unsigned long uint64_t
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:642
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:644