clang  19.0.0git
UnixAPIChecker.cpp
Go to the documentation of this file.
1 //= UnixAPIChecker.h - Checks preconditions for various Unix APIs --*- 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 defines UnixAPIChecker, which is an assortment of checks on calls
10 // to various, widely used UNIX/Posix functions.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Basic/TargetInfo.h"
24 #include "llvm/ADT/STLExtras.h"
25 #include "llvm/ADT/SmallString.h"
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include <optional>
29 
30 using namespace clang;
31 using namespace ento;
32 
33 enum class OpenVariant {
34  /// The standard open() call:
35  /// int open(const char *path, int oflag, ...);
36  Open,
37 
38  /// The variant taking a directory file descriptor and a relative path:
39  /// int openat(int fd, const char *path, int oflag, ...);
40  OpenAt
41 };
42 
43 namespace {
44 
45 class UnixAPIMisuseChecker
46  : public Checker<check::PreCall, check::ASTDecl<TranslationUnitDecl>> {
47  const BugType BT_open{this, "Improper use of 'open'", categories::UnixAPI};
48  const BugType BT_getline{this, "Improper use of getdelim",
50  const BugType BT_pthreadOnce{this, "Improper use of 'pthread_once'",
52  const BugType BT_ArgumentNull{this, "NULL pointer", categories::UnixAPI};
53  mutable std::optional<uint64_t> Val_O_CREAT;
54 
56  EnsurePtrNotNull(SVal PtrVal, const Expr *PtrExpr, CheckerContext &C,
57  ProgramStateRef State, const StringRef PtrDescr,
58  std::optional<std::reference_wrapper<const BugType>> BT =
59  std::nullopt) const;
60 
61  ProgramStateRef EnsureGetdelimBufferAndSizeCorrect(
62  SVal LinePtrPtrSVal, SVal SizePtrSVal, const Expr *LinePtrPtrExpr,
63  const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const;
64 
65 public:
66  void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager &Mgr,
67  BugReporter &BR) const;
68 
69  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
70 
71  void CheckOpen(CheckerContext &C, const CallEvent &Call) const;
72  void CheckOpenAt(CheckerContext &C, const CallEvent &Call) const;
73  void CheckGetDelim(CheckerContext &C, const CallEvent &Call) const;
74  void CheckPthreadOnce(CheckerContext &C, const CallEvent &Call) const;
75 
76  void CheckOpenVariant(CheckerContext &C, const CallEvent &Call,
77  OpenVariant Variant) const;
78 
79  void ReportOpenBug(CheckerContext &C, ProgramStateRef State, const char *Msg,
80  SourceRange SR) const;
81 };
82 
83 class UnixAPIPortabilityChecker : public Checker< check::PreStmt<CallExpr> > {
84 public:
85  void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
86 
87 private:
88  const BugType BT_mallocZero{
89  this, "Undefined allocation of 0 bytes (CERT MEM04-C; CWE-131)",
91 
92  void CheckCallocZero(CheckerContext &C, const CallExpr *CE) const;
93  void CheckMallocZero(CheckerContext &C, const CallExpr *CE) const;
94  void CheckReallocZero(CheckerContext &C, const CallExpr *CE) const;
95  void CheckReallocfZero(CheckerContext &C, const CallExpr *CE) const;
96  void CheckAllocaZero(CheckerContext &C, const CallExpr *CE) const;
97  void CheckAllocaWithAlignZero(CheckerContext &C, const CallExpr *CE) const;
98  void CheckVallocZero(CheckerContext &C, const CallExpr *CE) const;
99 
100  bool ReportZeroByteAllocation(CheckerContext &C,
101  ProgramStateRef falseState,
102  const Expr *arg,
103  const char *fn_name) const;
104  void BasicAllocationCheck(CheckerContext &C,
105  const CallExpr *CE,
106  const unsigned numArgs,
107  const unsigned sizeArg,
108  const char *fn) const;
109 };
110 
111 } // end anonymous namespace
112 
113 ProgramStateRef UnixAPIMisuseChecker::EnsurePtrNotNull(
114  SVal PtrVal, const Expr *PtrExpr, CheckerContext &C, ProgramStateRef State,
115  const StringRef PtrDescr,
116  std::optional<std::reference_wrapper<const BugType>> BT) const {
117  const auto Ptr = PtrVal.getAs<DefinedSVal>();
118  if (!Ptr)
119  return State;
120 
121  const auto [PtrNotNull, PtrNull] = State->assume(*Ptr);
122  if (!PtrNotNull && PtrNull) {
123  if (ExplodedNode *N = C.generateErrorNode(PtrNull)) {
124  auto R = std::make_unique<PathSensitiveBugReport>(
125  BT.value_or(std::cref(BT_ArgumentNull)),
126  (PtrDescr + " pointer might be NULL.").str(), N);
127  if (PtrExpr)
128  bugreporter::trackExpressionValue(N, PtrExpr, *R);
129  C.emitReport(std::move(R));
130  }
131  return nullptr;
132  }
133 
134  return PtrNotNull;
135 }
136 
137 void UnixAPIMisuseChecker::checkASTDecl(const TranslationUnitDecl *TU,
138  AnalysisManager &Mgr,
139  BugReporter &) const {
140  // The definition of O_CREAT is platform specific.
141  // Try to get the macro value from the preprocessor.
142  Val_O_CREAT = tryExpandAsInteger("O_CREAT", Mgr.getPreprocessor());
143  // If we failed, fall-back to known values.
144  if (!Val_O_CREAT) {
145  if (TU->getASTContext().getTargetInfo().getTriple().getVendor() ==
146  llvm::Triple::Apple)
147  Val_O_CREAT = 0x0200;
148  }
149 }
150 
151 //===----------------------------------------------------------------------===//
152 // "open" (man 2 open)
153 //===----------------------------------------------------------------------===/
154 
155 void UnixAPIMisuseChecker::checkPreCall(const CallEvent &Call,
156  CheckerContext &C) const {
157  const FunctionDecl *FD = dyn_cast_if_present<FunctionDecl>(Call.getDecl());
158  if (!FD || FD->getKind() != Decl::Function)
159  return;
160 
161  // Don't treat functions in namespaces with the same name a Unix function
162  // as a call to the Unix function.
163  const DeclContext *NamespaceCtx = FD->getEnclosingNamespaceContext();
164  if (isa_and_nonnull<NamespaceDecl>(NamespaceCtx))
165  return;
166 
167  StringRef FName = C.getCalleeName(FD);
168  if (FName.empty())
169  return;
170 
171  if (FName == "open")
172  CheckOpen(C, Call);
173 
174  else if (FName == "openat")
175  CheckOpenAt(C, Call);
176 
177  else if (FName == "pthread_once")
178  CheckPthreadOnce(C, Call);
179 
180  else if (is_contained({"getdelim", "getline"}, FName))
181  CheckGetDelim(C, Call);
182 }
183 void UnixAPIMisuseChecker::ReportOpenBug(CheckerContext &C,
185  const char *Msg,
186  SourceRange SR) const {
187  ExplodedNode *N = C.generateErrorNode(State);
188  if (!N)
189  return;
190 
191  auto Report = std::make_unique<PathSensitiveBugReport>(BT_open, Msg, N);
192  Report->addRange(SR);
193  C.emitReport(std::move(Report));
194 }
195 
196 void UnixAPIMisuseChecker::CheckOpen(CheckerContext &C,
197  const CallEvent &Call) const {
198  CheckOpenVariant(C, Call, OpenVariant::Open);
199 }
200 
201 void UnixAPIMisuseChecker::CheckOpenAt(CheckerContext &C,
202  const CallEvent &Call) const {
203  CheckOpenVariant(C, Call, OpenVariant::OpenAt);
204 }
205 
206 void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
207  const CallEvent &Call,
208  OpenVariant Variant) const {
209  // The index of the argument taking the flags open flags (O_RDONLY,
210  // O_WRONLY, O_CREAT, etc.),
211  unsigned int FlagsArgIndex;
212  const char *VariantName;
213  switch (Variant) {
214  case OpenVariant::Open:
215  FlagsArgIndex = 1;
216  VariantName = "open";
217  break;
218  case OpenVariant::OpenAt:
219  FlagsArgIndex = 2;
220  VariantName = "openat";
221  break;
222  };
223 
224  // All calls should at least provide arguments up to the 'flags' parameter.
225  unsigned int MinArgCount = FlagsArgIndex + 1;
226 
227  // If the flags has O_CREAT set then open/openat() require an additional
228  // argument specifying the file mode (permission bits) for the created file.
229  unsigned int CreateModeArgIndex = FlagsArgIndex + 1;
230 
231  // The create mode argument should be the last argument.
232  unsigned int MaxArgCount = CreateModeArgIndex + 1;
233 
234  ProgramStateRef state = C.getState();
235 
236  if (Call.getNumArgs() < MinArgCount) {
237  // The frontend should issue a warning for this case. Just return.
238  return;
239  } else if (Call.getNumArgs() == MaxArgCount) {
240  const Expr *Arg = Call.getArgExpr(CreateModeArgIndex);
241  QualType QT = Arg->getType();
242  if (!QT->isIntegerType()) {
243  SmallString<256> SBuf;
244  llvm::raw_svector_ostream OS(SBuf);
245  OS << "The " << CreateModeArgIndex + 1
246  << llvm::getOrdinalSuffix(CreateModeArgIndex + 1)
247  << " argument to '" << VariantName << "' is not an integer";
248 
249  ReportOpenBug(C, state,
250  SBuf.c_str(),
251  Arg->getSourceRange());
252  return;
253  }
254  } else if (Call.getNumArgs() > MaxArgCount) {
255  SmallString<256> SBuf;
256  llvm::raw_svector_ostream OS(SBuf);
257  OS << "Call to '" << VariantName << "' with more than " << MaxArgCount
258  << " arguments";
259 
260  ReportOpenBug(C, state, SBuf.c_str(),
261  Call.getArgExpr(MaxArgCount)->getSourceRange());
262  return;
263  }
264 
265  if (!Val_O_CREAT) {
266  return;
267  }
268 
269  // Now check if oflags has O_CREAT set.
270  const Expr *oflagsEx = Call.getArgExpr(FlagsArgIndex);
271  const SVal V = Call.getArgSVal(FlagsArgIndex);
272  if (!isa<NonLoc>(V)) {
273  // The case where 'V' can be a location can only be due to a bad header,
274  // so in this case bail out.
275  return;
276  }
277  NonLoc oflags = V.castAs<NonLoc>();
278  NonLoc ocreateFlag = C.getSValBuilder()
279  .makeIntVal(*Val_O_CREAT, oflagsEx->getType())
280  .castAs<NonLoc>();
281  SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And,
282  oflags, ocreateFlag,
283  oflagsEx->getType());
284  if (maskedFlagsUC.isUnknownOrUndef())
285  return;
286  DefinedSVal maskedFlags = maskedFlagsUC.castAs<DefinedSVal>();
287 
288  // Check if maskedFlags is non-zero.
289  ProgramStateRef trueState, falseState;
290  std::tie(trueState, falseState) = state->assume(maskedFlags);
291 
292  // Only emit an error if the value of 'maskedFlags' is properly
293  // constrained;
294  if (!(trueState && !falseState))
295  return;
296 
297  if (Call.getNumArgs() < MaxArgCount) {
298  SmallString<256> SBuf;
299  llvm::raw_svector_ostream OS(SBuf);
300  OS << "Call to '" << VariantName << "' requires a "
301  << CreateModeArgIndex + 1
302  << llvm::getOrdinalSuffix(CreateModeArgIndex + 1)
303  << " argument when the 'O_CREAT' flag is set";
304  ReportOpenBug(C, trueState,
305  SBuf.c_str(),
306  oflagsEx->getSourceRange());
307  }
308 }
309 
310 //===----------------------------------------------------------------------===//
311 // getdelim and getline
312 //===----------------------------------------------------------------------===//
313 
314 ProgramStateRef UnixAPIMisuseChecker::EnsureGetdelimBufferAndSizeCorrect(
315  SVal LinePtrPtrSVal, SVal SizePtrSVal, const Expr *LinePtrPtrExpr,
316  const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const {
317  static constexpr llvm::StringLiteral SizeGreaterThanBufferSize =
318  "The buffer from the first argument is smaller than the size "
319  "specified by the second parameter";
320  static constexpr llvm::StringLiteral SizeUndef =
321  "The buffer from the first argument is not NULL, but the size specified "
322  "by the second parameter is undefined.";
323 
324  auto EmitBugReport = [this, &C, SizePtrExpr, LinePtrPtrExpr](
325  ProgramStateRef BugState, StringRef ErrMsg) {
326  if (ExplodedNode *N = C.generateErrorNode(BugState)) {
327  auto R = std::make_unique<PathSensitiveBugReport>(BT_getline, ErrMsg, N);
328  bugreporter::trackExpressionValue(N, SizePtrExpr, *R);
329  bugreporter::trackExpressionValue(N, LinePtrPtrExpr, *R);
330  C.emitReport(std::move(R));
331  }
332  };
333 
334  // We have a pointer to a pointer to the buffer, and a pointer to the size.
335  // We want what they point at.
336  auto LinePtrSVal = getPointeeVal(LinePtrPtrSVal, State)->getAs<DefinedSVal>();
337  auto NSVal = getPointeeVal(SizePtrSVal, State);
338  if (!LinePtrSVal || !NSVal || NSVal->isUnknown())
339  return nullptr;
340 
341  assert(LinePtrPtrExpr && SizePtrExpr);
342 
343  const auto [LinePtrNotNull, LinePtrNull] = State->assume(*LinePtrSVal);
344  if (LinePtrNotNull && !LinePtrNull) {
345  // If `*lineptr` is not null, but `*n` is undefined, there is UB.
346  if (NSVal->isUndef()) {
347  EmitBugReport(LinePtrNotNull, SizeUndef);
348  return nullptr;
349  }
350 
351  // If it is defined, and known, its size must be less than or equal to
352  // the buffer size.
353  auto NDefSVal = NSVal->getAs<DefinedSVal>();
354  auto &SVB = C.getSValBuilder();
355  auto LineBufSize =
356  getDynamicExtent(LinePtrNotNull, LinePtrSVal->getAsRegion(), SVB);
357  auto LineBufSizeGtN = SVB.evalBinOp(LinePtrNotNull, BO_GE, LineBufSize,
358  *NDefSVal, SVB.getConditionType())
360  if (!LineBufSizeGtN)
361  return LinePtrNotNull;
362  if (auto LineBufSizeOk = LinePtrNotNull->assume(*LineBufSizeGtN, true))
363  return LineBufSizeOk;
364 
365  EmitBugReport(LinePtrNotNull, SizeGreaterThanBufferSize);
366  return nullptr;
367  }
368  return State;
369 }
370 
371 void UnixAPIMisuseChecker::CheckGetDelim(CheckerContext &C,
372  const CallEvent &Call) const {
373  ProgramStateRef State = C.getState();
374 
375  // The parameter `n` must not be NULL.
376  SVal SizePtrSval = Call.getArgSVal(1);
377  State = EnsurePtrNotNull(SizePtrSval, Call.getArgExpr(1), C, State, "Size");
378  if (!State)
379  return;
380 
381  // The parameter `lineptr` must not be NULL.
382  SVal LinePtrPtrSVal = Call.getArgSVal(0);
383  State =
384  EnsurePtrNotNull(LinePtrPtrSVal, Call.getArgExpr(0), C, State, "Line");
385  if (!State)
386  return;
387 
388  State = EnsureGetdelimBufferAndSizeCorrect(LinePtrPtrSVal, SizePtrSval,
389  Call.getArgExpr(0),
390  Call.getArgExpr(1), C, State);
391  if (!State)
392  return;
393 
394  C.addTransition(State);
395 }
396 
397 //===----------------------------------------------------------------------===//
398 // pthread_once
399 //===----------------------------------------------------------------------===//
400 
401 void UnixAPIMisuseChecker::CheckPthreadOnce(CheckerContext &C,
402  const CallEvent &Call) const {
403 
404  // This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker.
405  // They can possibly be refactored.
406 
407  if (Call.getNumArgs() < 1)
408  return;
409 
410  // Check if the first argument is stack allocated. If so, issue a warning
411  // because that's likely to be bad news.
412  ProgramStateRef state = C.getState();
413  const MemRegion *R = Call.getArgSVal(0).getAsRegion();
414  if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
415  return;
416 
417  ExplodedNode *N = C.generateErrorNode(state);
418  if (!N)
419  return;
420 
422  llvm::raw_svector_ostream os(S);
423  os << "Call to 'pthread_once' uses";
424  if (const VarRegion *VR = dyn_cast<VarRegion>(R))
425  os << " the local variable '" << VR->getDecl()->getName() << '\'';
426  else
427  os << " stack allocated memory";
428  os << " for the \"control\" value. Using such transient memory for "
429  "the control value is potentially dangerous.";
430  if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
431  os << " Perhaps you intended to declare the variable as 'static'?";
432 
433  auto report =
434  std::make_unique<PathSensitiveBugReport>(BT_pthreadOnce, os.str(), N);
435  report->addRange(Call.getArgExpr(0)->getSourceRange());
436  C.emitReport(std::move(report));
437 }
438 
439 //===----------------------------------------------------------------------===//
440 // "calloc", "malloc", "realloc", "reallocf", "alloca" and "valloc"
441 // with allocation size 0
442 //===----------------------------------------------------------------------===//
443 
444 // FIXME: Eventually these should be rolled into the MallocChecker, but right now
445 // they're more basic and valuable for widespread use.
446 
447 // Returns true if we try to do a zero byte allocation, false otherwise.
448 // Fills in trueState and falseState.
450  const SVal argVal,
451  ProgramStateRef *trueState,
452  ProgramStateRef *falseState) {
453  std::tie(*trueState, *falseState) =
454  state->assume(argVal.castAs<DefinedSVal>());
455 
456  return (*falseState && !*trueState);
457 }
458 
459 // Generates an error report, indicating that the function whose name is given
460 // will perform a zero byte allocation.
461 // Returns false if an error occurred, true otherwise.
462 bool UnixAPIPortabilityChecker::ReportZeroByteAllocation(
463  CheckerContext &C,
464  ProgramStateRef falseState,
465  const Expr *arg,
466  const char *fn_name) const {
467  ExplodedNode *N = C.generateErrorNode(falseState);
468  if (!N)
469  return false;
470 
472  llvm::raw_svector_ostream os(S);
473  os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";
474  auto report =
475  std::make_unique<PathSensitiveBugReport>(BT_mallocZero, os.str(), N);
476 
477  report->addRange(arg->getSourceRange());
479  C.emitReport(std::move(report));
480 
481  return true;
482 }
483 
484 // Does a basic check for 0-sized allocations suitable for most of the below
485 // functions (modulo "calloc")
486 void UnixAPIPortabilityChecker::BasicAllocationCheck(CheckerContext &C,
487  const CallExpr *CE,
488  const unsigned numArgs,
489  const unsigned sizeArg,
490  const char *fn) const {
491  // Check for the correct number of arguments.
492  if (CE->getNumArgs() != numArgs)
493  return;
494 
495  // Check if the allocation size is 0.
496  ProgramStateRef state = C.getState();
497  ProgramStateRef trueState = nullptr, falseState = nullptr;
498  const Expr *arg = CE->getArg(sizeArg);
499  SVal argVal = C.getSVal(arg);
500 
501  if (argVal.isUnknownOrUndef())
502  return;
503 
504  // Is the value perfectly constrained to zero?
505  if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
506  (void) ReportZeroByteAllocation(C, falseState, arg, fn);
507  return;
508  }
509  // Assume the value is non-zero going forward.
510  assert(trueState);
511  if (trueState != state)
512  C.addTransition(trueState);
513 }
514 
515 void UnixAPIPortabilityChecker::CheckCallocZero(CheckerContext &C,
516  const CallExpr *CE) const {
517  unsigned int nArgs = CE->getNumArgs();
518  if (nArgs != 2)
519  return;
520 
521  ProgramStateRef state = C.getState();
522  ProgramStateRef trueState = nullptr, falseState = nullptr;
523 
524  unsigned int i;
525  for (i = 0; i < nArgs; i++) {
526  const Expr *arg = CE->getArg(i);
527  SVal argVal = C.getSVal(arg);
528  if (argVal.isUnknownOrUndef()) {
529  if (i == 0)
530  continue;
531  else
532  return;
533  }
534 
535  if (IsZeroByteAllocation(state, argVal, &trueState, &falseState)) {
536  if (ReportZeroByteAllocation(C, falseState, arg, "calloc"))
537  return;
538  else if (i == 0)
539  continue;
540  else
541  return;
542  }
543  }
544 
545  // Assume the value is non-zero going forward.
546  assert(trueState);
547  if (trueState != state)
548  C.addTransition(trueState);
549 }
550 
551 void UnixAPIPortabilityChecker::CheckMallocZero(CheckerContext &C,
552  const CallExpr *CE) const {
553  BasicAllocationCheck(C, CE, 1, 0, "malloc");
554 }
555 
556 void UnixAPIPortabilityChecker::CheckReallocZero(CheckerContext &C,
557  const CallExpr *CE) const {
558  BasicAllocationCheck(C, CE, 2, 1, "realloc");
559 }
560 
561 void UnixAPIPortabilityChecker::CheckReallocfZero(CheckerContext &C,
562  const CallExpr *CE) const {
563  BasicAllocationCheck(C, CE, 2, 1, "reallocf");
564 }
565 
566 void UnixAPIPortabilityChecker::CheckAllocaZero(CheckerContext &C,
567  const CallExpr *CE) const {
568  BasicAllocationCheck(C, CE, 1, 0, "alloca");
569 }
570 
571 void UnixAPIPortabilityChecker::CheckAllocaWithAlignZero(
572  CheckerContext &C,
573  const CallExpr *CE) const {
574  BasicAllocationCheck(C, CE, 2, 0, "__builtin_alloca_with_align");
575 }
576 
577 void UnixAPIPortabilityChecker::CheckVallocZero(CheckerContext &C,
578  const CallExpr *CE) const {
579  BasicAllocationCheck(C, CE, 1, 0, "valloc");
580 }
581 
582 void UnixAPIPortabilityChecker::checkPreStmt(const CallExpr *CE,
583  CheckerContext &C) const {
584  const FunctionDecl *FD = C.getCalleeDecl(CE);
585  if (!FD || FD->getKind() != Decl::Function)
586  return;
587 
588  // Don't treat functions in namespaces with the same name a Unix function
589  // as a call to the Unix function.
590  const DeclContext *NamespaceCtx = FD->getEnclosingNamespaceContext();
591  if (isa_and_nonnull<NamespaceDecl>(NamespaceCtx))
592  return;
593 
594  StringRef FName = C.getCalleeName(FD);
595  if (FName.empty())
596  return;
597 
598  if (FName == "calloc")
599  CheckCallocZero(C, CE);
600 
601  else if (FName == "malloc")
602  CheckMallocZero(C, CE);
603 
604  else if (FName == "realloc")
605  CheckReallocZero(C, CE);
606 
607  else if (FName == "reallocf")
608  CheckReallocfZero(C, CE);
609 
610  else if (FName == "alloca" || FName == "__builtin_alloca")
611  CheckAllocaZero(C, CE);
612 
613  else if (FName == "__builtin_alloca_with_align")
614  CheckAllocaWithAlignZero(C, CE);
615 
616  else if (FName == "valloc")
617  CheckVallocZero(C, CE);
618 }
619 
620 //===----------------------------------------------------------------------===//
621 // Registration.
622 //===----------------------------------------------------------------------===//
623 
624 #define REGISTER_CHECKER(CHECKERNAME) \
625  void ento::register##CHECKERNAME(CheckerManager &mgr) { \
626  mgr.registerChecker<CHECKERNAME>(); \
627  } \
628  \
629  bool ento::shouldRegister##CHECKERNAME(const CheckerManager &mgr) { \
630  return true; \
631  }
632 
633 REGISTER_CHECKER(UnixAPIMisuseChecker)
634 REGISTER_CHECKER(UnixAPIPortabilityChecker)
#define V(N, I)
Definition: ASTContext.h:3299
static bool IsZeroByteAllocation(ProgramStateRef state, const SVal argVal, ProgramStateRef *trueState, ProgramStateRef *falseState)
OpenVariant
@ OpenAt
The variant taking a directory file descriptor and a relative path: int openat(int fd,...
@ Open
The standard open() call: int open(const char *path, int oflag, ...);.
#define REGISTER_CHECKER(CHECKERNAME)
LineState State
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:760
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2872
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3050
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3063
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1436
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
Definition: DeclBase.cpp:1956
Kind getKind() const
Definition: DeclBase.h:448
This represents one expression.
Definition: Expr.h:110
QualType getType() const
Definition: Expr.h:142
Represents a function declaration or definition.
Definition: Decl.h:1972
A (possibly-)qualified type.
Definition: Type.h:940
A trivial tuple used to represent a source range.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1256
The top declaration context.
Definition: Decl.h:84
ASTContext & getASTContext() const
Definition: Decl.h:120
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:7979
Preprocessor & getPreprocessor() override
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:585
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:153
bool isUndef() const =delete
bool isUnknown() const =delete
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:96
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace() const
Definition: MemRegion.cpp:1317
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:55
bool isUnknownOrUndef() const
Definition: SVals.h:106
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
Definition: SVals.h:86
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition: SVals.h:82
Defines the clang::TargetInfo interface.
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB)
std::optional< SVal > getPointeeVal(SVal PtrSVal, ProgramStateRef State)
std::optional< int > tryExpandAsInteger(StringRef Macro, const Preprocessor &PP)
Try to parse the value of a defined preprocessor macro.
bool Call(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
Definition: Interp.h:2179
The JSON file list parser is used to communicate input to InstallAPI.
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)
Definition: complex_cmath.h:40