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
20#include "llvm/ADT/SmallString.h"
21#include "llvm/ADT/StringSwitch.h"
22#include "llvm/Support/raw_ostream.h"
23
24using namespace clang;
25using namespace ento;
26
27static 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
36namespace {
37struct 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
69class 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
78public:
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
125void WalkAST::VisitChildren(Stmt *S) {
126 for (Stmt *Child : S->children())
127 if (Child)
128 Visit(Child);
129}
130
131void 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
189void 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
203void 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
212void 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.
226static const DeclRefExpr*
227getIncrementedVar(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///
260void 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
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
347void 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.
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
389void 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.
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
432void 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.
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
474void 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.
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
510void 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.
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
550void 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.
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
591void 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)
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.
649 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
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
676void 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.
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
715void 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.
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
752void 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
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
822bool 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
858void 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
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().
897void 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.
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
925void 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.
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
949void 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
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
1008void 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
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
1072namespace {
1073class SecuritySyntaxChecker : public Checker<check::ASTCodeBody> {
1074public:
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
1085void ento::registerSecuritySyntaxChecker(CheckerManager &mgr) {
1086 mgr.registerChecker<SecuritySyntaxChecker>();
1087}
1088
1089bool 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
1102REGISTER_CHECKER(bcmp)
1103REGISTER_CHECKER(bcopy)
1104REGISTER_CHECKER(bzero)
1105REGISTER_CHECKER(gets)
1106REGISTER_CHECKER(getpw)
1107REGISTER_CHECKER(mkstemp)
1108REGISTER_CHECKER(mktemp)
1109REGISTER_CHECKER(strcpy)
1110REGISTER_CHECKER(rand)
1111REGISTER_CHECKER(vfork)
1112REGISTER_CHECKER(FloatLoopCounter)
1113REGISTER_CHECKER(UncheckedReturn)
1114REGISTER_CHECKER(DeprecatedOrUnsafeBufferHandling)
1115REGISTER_CHECKER(decodeValueOfObjCType)
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
#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:3840
Expr * getLHS() const
Definition: Expr.h:3889
static bool isRelationalOp(Opcode Opc)
Definition: Expr.h:3933
Expr * getRHS() const
Definition: Expr.h:3891
static bool isEqualityOp(Opcode Opc)
Definition: Expr.h:3936
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2820
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3011
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:2990
Expr * getCallee()
Definition: Expr.h:2970
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:2998
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:3064
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition: Expr.cpp:3076
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3059
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3039
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:1971
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4657
unsigned getNumParams() const
Definition: Type.h:4890
QualType getParamType(unsigned i) const
Definition: Type.h:4892
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
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276
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:3140
QualType getPointeeType() const
Definition: Type.h:3150
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7454
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
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1256
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
Definition: TargetInfo.h:1648
bool isIntegralOrUnscopedEnumerationType() const
Determine whether this type is an integral or unscoped enumeration type.
Definition: Type.cpp:2060
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2255
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8131
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2183
QualType getType() const
Definition: Decl.h:717
Represents a variable declaration or definition.
Definition: Decl.h:918
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