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