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