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