clang 22.0.0git
MallocChecker.cpp
Go to the documentation of this file.
1//=== MallocChecker.cpp - A malloc/free checker -------------------*- 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 checkers that report memory management errors such as
10// leak, double free, and use-after-free.
11//
12// The logic for modeling memory allocations is implemented in the checker
13// family which is called 'MallocChecker' for historical reasons. (This name is
14// inaccurate, something like 'DynamicMemory' would be more precise.)
15//
16// The reports produced by this backend are exposed through several frontends:
17// * MallocChecker: reports all misuse of dynamic memory allocated by
18// malloc, related functions (like calloc, realloc etc.) and the functions
19// annotated by ownership_returns. (Here the name "MallocChecker" is
20// reasonably accurate; don't confuse this checker frontend with the whole
21// misnamed family.)
22// * NewDeleteChecker: reports most misuse (anything but memory leaks) of
23// memory managed by the C++ operators new and new[].
24// * NewDeleteLeaksChecker: reports leaks of dynamic memory allocated by
25// the C++ operators new and new[].
26// * MismatchedDeallocatorChecker: reports situations where the allocation
27// and deallocation is mismatched, e.g. memory allocated via malloc is
28// passed to operator delete.
29// * InnerPointerChecker: reports use of pointers to the internal buffer of
30// a std::string instance after operations that invalidate them.
31// * TaintedAllocChecker: reports situations where the size argument of a
32// memory allocation function or array new operator is tainted (i.e. comes
33// from an untrusted source and can be controlled by an attacker).
34//
35// In addition to these frontends this file also defines the registration
36// functions for "unix.DynamicMemoryModeling". This registers the callbacks of
37// the checker family MallocChecker without enabling any of the frontends and
38// and handle two checker options which are attached to this "modeling
39// checker" because they affect multiple checker frontends.
40//
41// Note that what the users see as the checker "cplusplus.InnerPointer" is a
42// combination of the frontend InnerPointerChecker (within this family) which
43// emits the bug reports and a separate checker class (also named
44// InnerPointerChecker) which is defined in InnerPointerChecker.cpp and does a
45// significant part of the modeling. This cooperation is enabled by several
46// non-static helper functions that are defined within this translation unit
47// and used in InnerPointerChecker.cpp.
48//
49//===----------------------------------------------------------------------===//
50
51#include "AllocationState.h"
52#include "InterCheckerAPI.h"
54#include "clang/AST/Attr.h"
55#include "clang/AST/DeclCXX.h"
57#include "clang/AST/Expr.h"
58#include "clang/AST/ExprCXX.h"
59#include "clang/AST/ParentMap.h"
63#include "clang/Basic/LLVM.h"
66#include "clang/Lex/Lexer.h"
84#include "llvm/ADT/STLExtras.h"
85#include "llvm/ADT/SmallVector.h"
86#include "llvm/ADT/StringExtras.h"
87#include "llvm/Support/Casting.h"
88#include "llvm/Support/Compiler.h"
89#include "llvm/Support/ErrorHandling.h"
90#include "llvm/Support/raw_ostream.h"
91#include <functional>
92#include <optional>
93#include <utility>
94
95using namespace clang;
96using namespace ento;
97using namespace std::placeholders;
98
99//===----------------------------------------------------------------------===//
100// The types of allocation we're modeling. This is used to check whether a
101// dynamically allocated object is deallocated with the correct function, like
102// not using operator delete on an object created by malloc(), or alloca regions
103// aren't ever deallocated manually.
104//===----------------------------------------------------------------------===//
105
106namespace {
107
108// Used to check correspondence between allocators and deallocators.
109enum AllocationFamilyKind {
110 AF_None,
111 AF_Malloc,
112 AF_CXXNew,
113 AF_CXXNewArray,
114 AF_IfNameIndex,
115 AF_Alloca,
116 AF_InnerBuffer,
117 AF_Custom,
118};
119
120struct AllocationFamily {
121 AllocationFamilyKind Kind;
122 std::optional<StringRef> CustomName;
123
124 explicit AllocationFamily(AllocationFamilyKind AKind,
125 std::optional<StringRef> Name = std::nullopt)
126 : Kind(AKind), CustomName(Name) {
127 assert((Kind != AF_Custom || CustomName.has_value()) &&
128 "Custom family must specify also the name");
129
130 // Preseve previous behavior when "malloc" class means AF_Malloc
131 if (Kind == AF_Custom && CustomName.value() == "malloc") {
132 Kind = AF_Malloc;
133 CustomName = std::nullopt;
134 }
135 }
136
137 bool operator==(const AllocationFamily &Other) const {
138 return std::tie(Kind, CustomName) == std::tie(Other.Kind, Other.CustomName);
139 }
140
141 bool operator!=(const AllocationFamily &Other) const {
142 return !(*this == Other);
143 }
144
145 void Profile(llvm::FoldingSetNodeID &ID) const {
146 ID.AddInteger(Kind);
147
148 if (Kind == AF_Custom)
149 ID.AddString(CustomName.value());
150 }
151};
152
153} // end of anonymous namespace
154
155/// Print names of allocators and deallocators.
156///
157/// \returns true on success.
158static bool printMemFnName(raw_ostream &os, CheckerContext &C, const Expr *E);
159
160/// Print expected name of an allocator based on the deallocator's family
161/// derived from the DeallocExpr.
162static void printExpectedAllocName(raw_ostream &os, AllocationFamily Family);
163
164/// Print expected name of a deallocator based on the allocator's
165/// family.
166static void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family);
167
168//===----------------------------------------------------------------------===//
169// The state of a symbol, in terms of memory management.
170//===----------------------------------------------------------------------===//
171
172namespace {
173
174class RefState {
175 enum Kind {
176 // Reference to allocated memory.
177 Allocated,
178 // Reference to zero-allocated memory.
179 AllocatedOfSizeZero,
180 // Reference to released/freed memory.
181 Released,
182 // The responsibility for freeing resources has transferred from
183 // this reference. A relinquished symbol should not be freed.
184 Relinquished,
185 // We are no longer guaranteed to have observed all manipulations
186 // of this pointer/memory. For example, it could have been
187 // passed as a parameter to an opaque function.
188 Escaped
189 };
190
191 const Stmt *S;
192
193 Kind K;
194 AllocationFamily Family;
195
196 RefState(Kind k, const Stmt *s, AllocationFamily family)
197 : S(s), K(k), Family(family) {
198 assert(family.Kind != AF_None);
199 }
200
201public:
202 bool isAllocated() const { return K == Allocated; }
203 bool isAllocatedOfSizeZero() const { return K == AllocatedOfSizeZero; }
204 bool isReleased() const { return K == Released; }
205 bool isRelinquished() const { return K == Relinquished; }
206 bool isEscaped() const { return K == Escaped; }
207 AllocationFamily getAllocationFamily() const { return Family; }
208 const Stmt *getStmt() const { return S; }
209
210 bool operator==(const RefState &X) const {
211 return K == X.K && S == X.S && Family == X.Family;
212 }
213
214 static RefState getAllocated(AllocationFamily family, const Stmt *s) {
215 return RefState(Allocated, s, family);
216 }
217 static RefState getAllocatedOfSizeZero(const RefState *RS) {
218 return RefState(AllocatedOfSizeZero, RS->getStmt(),
219 RS->getAllocationFamily());
220 }
221 static RefState getReleased(AllocationFamily family, const Stmt *s) {
222 return RefState(Released, s, family);
223 }
224 static RefState getRelinquished(AllocationFamily family, const Stmt *s) {
225 return RefState(Relinquished, s, family);
226 }
227 static RefState getEscaped(const RefState *RS) {
228 return RefState(Escaped, RS->getStmt(), RS->getAllocationFamily());
229 }
230
231 void Profile(llvm::FoldingSetNodeID &ID) const {
232 ID.AddInteger(K);
233 ID.AddPointer(S);
234 Family.Profile(ID);
235 }
236
237 LLVM_DUMP_METHOD void dump(raw_ostream &OS) const {
238 switch (K) {
239#define CASE(ID) case ID: OS << #ID; break;
240 CASE(Allocated)
241 CASE(AllocatedOfSizeZero)
242 CASE(Released)
243 CASE(Relinquished)
244 CASE(Escaped)
245 }
246 }
247
248 LLVM_DUMP_METHOD void dump() const { dump(llvm::errs()); }
249};
250
251} // end of anonymous namespace
252
253REGISTER_MAP_WITH_PROGRAMSTATE(RegionState, SymbolRef, RefState)
254
255/// Check if the memory associated with this symbol was released.
256static bool isReleased(SymbolRef Sym, CheckerContext &C);
257
258/// Update the RefState to reflect the new memory allocation.
259/// The optional \p RetVal parameter specifies the newly allocated pointer
260/// value; if unspecified, the value of expression \p E is used.
261static ProgramStateRef
263 AllocationFamily Family,
264 std::optional<SVal> RetVal = std::nullopt);
265
266//===----------------------------------------------------------------------===//
267// The modeling of memory reallocation.
268//
269// The terminology 'toPtr' and 'fromPtr' will be used:
270// toPtr = realloc(fromPtr, 20);
271//===----------------------------------------------------------------------===//
272
273REGISTER_SET_WITH_PROGRAMSTATE(ReallocSizeZeroSymbols, SymbolRef)
274
275namespace {
276
277/// The state of 'fromPtr' after reallocation is known to have failed.
278enum OwnershipAfterReallocKind {
279 // The symbol needs to be freed (e.g.: realloc)
280 OAR_ToBeFreedAfterFailure,
281 // The symbol has been freed (e.g.: reallocf)
282 OAR_FreeOnFailure,
283 // The symbol doesn't have to freed (e.g.: we aren't sure if, how and where
284 // 'fromPtr' was allocated:
285 // void Haha(int *ptr) {
286 // ptr = realloc(ptr, 67);
287 // // ...
288 // }
289 // ).
290 OAR_DoNotTrackAfterFailure
291};
292
293/// Stores information about the 'fromPtr' symbol after reallocation.
294///
295/// This is important because realloc may fail, and that needs special modeling.
296/// Whether reallocation failed or not will not be known until later, so we'll
297/// store whether upon failure 'fromPtr' will be freed, or needs to be freed
298/// later, etc.
299struct ReallocPair {
300
301 // The 'fromPtr'.
302 SymbolRef ReallocatedSym;
303 OwnershipAfterReallocKind Kind;
304
305 ReallocPair(SymbolRef S, OwnershipAfterReallocKind K)
306 : ReallocatedSym(S), Kind(K) {}
307 void Profile(llvm::FoldingSetNodeID &ID) const {
308 ID.AddInteger(Kind);
309 ID.AddPointer(ReallocatedSym);
310 }
311 bool operator==(const ReallocPair &X) const {
312 return ReallocatedSym == X.ReallocatedSym &&
313 Kind == X.Kind;
314 }
315};
316
317} // end of anonymous namespace
318
319REGISTER_MAP_WITH_PROGRAMSTATE(ReallocPairs, SymbolRef, ReallocPair)
320
321static bool isStandardNew(const FunctionDecl *FD);
322static bool isStandardNew(const CallEvent &Call) {
323 if (!Call.getDecl() || !isa<FunctionDecl>(Call.getDecl()))
324 return false;
325 return isStandardNew(cast<FunctionDecl>(Call.getDecl()));
326}
327
328static bool isStandardDelete(const FunctionDecl *FD);
329static bool isStandardDelete(const CallEvent &Call) {
330 if (!Call.getDecl() || !isa<FunctionDecl>(Call.getDecl()))
331 return false;
332 return isStandardDelete(cast<FunctionDecl>(Call.getDecl()));
333}
334
335/// Tells if the callee is one of the builtin new/delete operators, including
336/// placement operators and other standard overloads.
337template <typename T> static bool isStandardNewDelete(const T &FD) {
338 return isStandardDelete(FD) || isStandardNew(FD);
339}
340
341namespace {
342
343//===----------------------------------------------------------------------===//
344// Utility classes that provide access to the bug types and can model that some
345// of the bug types are shared by multiple checker frontends.
346//===----------------------------------------------------------------------===//
347
348#define BUGTYPE_PROVIDER(NAME, DEF) \
349 struct NAME : virtual public CheckerFrontend { \
350 BugType NAME##Bug{this, DEF, categories::MemoryError}; \
351 };
352
353BUGTYPE_PROVIDER(DoubleFree, "Double free")
354
355struct Leak : virtual public CheckerFrontend {
356 // Leaks should not be reported if they are post-dominated by a sink:
357 // (1) Sinks are higher importance bugs.
358 // (2) NoReturnFunctionChecker uses sink nodes to represent paths ending
359 // with __noreturn functions such as assert() or exit(). We choose not
360 // to report leaks on such paths.
361 BugType LeakBug{this, "Memory leak", categories::MemoryError,
362 /*SuppressOnSink=*/true};
363};
364
365BUGTYPE_PROVIDER(UseFree, "Use-after-free")
366BUGTYPE_PROVIDER(BadFree, "Bad free")
367BUGTYPE_PROVIDER(FreeAlloca, "Free 'alloca()'")
368BUGTYPE_PROVIDER(MismatchedDealloc, "Bad deallocator")
369BUGTYPE_PROVIDER(OffsetFree, "Offset free")
370BUGTYPE_PROVIDER(UseZeroAllocated, "Use of zero allocated")
371
372#undef BUGTYPE_PROVIDER
373
374template <typename... BT_PROVIDERS>
375struct DynMemFrontend : virtual public CheckerFrontend, public BT_PROVIDERS... {
376 template <typename T> const T *getAs() const {
377 if constexpr (std::is_same_v<T, CheckerFrontend> ||
378 (std::is_same_v<T, BT_PROVIDERS> || ...))
379 return static_cast<const T *>(this);
380 return nullptr;
381 }
382};
383
384//===----------------------------------------------------------------------===//
385// Definition of the MallocChecker class.
386//===----------------------------------------------------------------------===//
387
388class MallocChecker
389 : public CheckerFamily<
390 check::DeadSymbols, check::PointerEscape, check::ConstPointerEscape,
391 check::PreStmt<ReturnStmt>, check::EndFunction, check::PreCall,
392 check::PostCall, eval::Call, check::NewAllocator,
393 check::PostStmt<BlockExpr>, check::PostObjCMessage, check::Location,
394 eval::Assume> {
395public:
396 /// In pessimistic mode, the checker assumes that it does not know which
397 /// functions might free the memory.
398 /// In optimistic mode, the checker assumes that all user-defined functions
399 /// which might free a pointer are annotated.
400 bool ShouldIncludeOwnershipAnnotatedFunctions = false;
401
402 bool ShouldRegisterNoOwnershipChangeVisitor = false;
403
404 // This checker family implements many bug types and frontends, and several
405 // bug types are shared between multiple frontends, so most of the frontends
406 // are declared with the helper class DynMemFrontend.
407 // FIXME: There is no clear reason for separating NewDelete vs NewDeleteLeaks
408 // while e.g. MallocChecker covers both non-leak and leak bugs together. It
409 // would be nice to redraw the boundaries between the frontends in a more
410 // logical way.
411 DynMemFrontend<DoubleFree, Leak, UseFree, BadFree, FreeAlloca, OffsetFree,
412 UseZeroAllocated>
413 MallocChecker;
414 DynMemFrontend<DoubleFree, UseFree, BadFree, OffsetFree, UseZeroAllocated>
415 NewDeleteChecker;
416 DynMemFrontend<Leak> NewDeleteLeaksChecker;
417 DynMemFrontend<FreeAlloca, MismatchedDealloc> MismatchedDeallocatorChecker;
418 DynMemFrontend<UseFree> InnerPointerChecker;
419 // This last frontend is associated with a single bug type which is not used
420 // elsewhere and has a different bug category, so it's declared separately.
421 CheckerFrontendWithBugType TaintedAllocChecker{"Tainted Memory Allocation",
423
424 using LeakInfo = std::pair<const ExplodedNode *, const MemRegion *>;
425
426 void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
427 void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
428 bool evalCall(const CallEvent &Call, CheckerContext &C) const;
429
431 handleSmartPointerConstructorArguments(const CallEvent &Call,
432 ProgramStateRef State) const;
433 ProgramStateRef handleSmartPointerRelatedCalls(const CallEvent &Call,
434 CheckerContext &C,
435 ProgramStateRef State) const;
436 void checkNewAllocator(const CXXAllocatorCall &Call, CheckerContext &C) const;
437 void checkPostObjCMessage(const ObjCMethodCall &Call, CheckerContext &C) const;
438 void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
439 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
440 void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
441 void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const;
442 ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
443 bool Assumption) const;
444 void checkLocation(SVal l, bool isLoad, const Stmt *S,
445 CheckerContext &C) const;
446
447 ProgramStateRef checkPointerEscape(ProgramStateRef State,
448 const InvalidatedSymbols &Escaped,
449 const CallEvent *Call,
450 PointerEscapeKind Kind) const;
451 ProgramStateRef checkConstPointerEscape(ProgramStateRef State,
452 const InvalidatedSymbols &Escaped,
453 const CallEvent *Call,
454 PointerEscapeKind Kind) const;
455
456 void printState(raw_ostream &Out, ProgramStateRef State,
457 const char *NL, const char *Sep) const override;
458
459 StringRef getDebugTag() const override { return "MallocChecker"; }
460
461private:
462#define CHECK_FN(NAME) \
463 void NAME(ProgramStateRef State, const CallEvent &Call, CheckerContext &C) \
464 const;
465
466 CHECK_FN(checkFree)
467 CHECK_FN(checkIfNameIndex)
468 CHECK_FN(checkBasicAlloc)
469 CHECK_FN(checkKernelMalloc)
470 CHECK_FN(checkCalloc)
471 CHECK_FN(checkAlloca)
472 CHECK_FN(checkStrdup)
473 CHECK_FN(checkIfFreeNameIndex)
474 CHECK_FN(checkCXXNewOrCXXDelete)
475 CHECK_FN(checkGMalloc0)
476 CHECK_FN(checkGMemdup)
477 CHECK_FN(checkGMallocN)
478 CHECK_FN(checkGMallocN0)
479 CHECK_FN(preGetDelimOrGetLine)
480 CHECK_FN(checkGetDelimOrGetLine)
481 CHECK_FN(checkReallocN)
482 CHECK_FN(checkOwnershipAttr)
483
484 void checkRealloc(ProgramStateRef State, const CallEvent &Call,
485 CheckerContext &C, bool ShouldFreeOnFail) const;
486
487 using CheckFn =
488 std::function<void(const class MallocChecker *, ProgramStateRef State,
489 const CallEvent &Call, CheckerContext &C)>;
490
491 const CallDescriptionMap<CheckFn> PreFnMap{
492 // NOTE: the following CallDescription also matches the C++ standard
493 // library function std::getline(); the callback will filter it out.
494 {{CDM::CLibrary, {"getline"}, 3}, &MallocChecker::preGetDelimOrGetLine},
495 {{CDM::CLibrary, {"getdelim"}, 4}, &MallocChecker::preGetDelimOrGetLine},
496 };
497
498 const CallDescriptionMap<CheckFn> PostFnMap{
499 // NOTE: the following CallDescription also matches the C++ standard
500 // library function std::getline(); the callback will filter it out.
501 {{CDM::CLibrary, {"getline"}, 3}, &MallocChecker::checkGetDelimOrGetLine},
502 {{CDM::CLibrary, {"getdelim"}, 4},
503 &MallocChecker::checkGetDelimOrGetLine},
504 };
505
506 const CallDescriptionMap<CheckFn> FreeingMemFnMap{
507 {{CDM::CLibrary, {"free"}, 1}, &MallocChecker::checkFree},
508 {{CDM::CLibrary, {"if_freenameindex"}, 1},
509 &MallocChecker::checkIfFreeNameIndex},
510 {{CDM::CLibrary, {"kfree"}, 1}, &MallocChecker::checkFree},
511 {{CDM::CLibrary, {"g_free"}, 1}, &MallocChecker::checkFree},
512 };
513
514 bool isFreeingCall(const CallEvent &Call) const;
515 static bool isFreeingOwnershipAttrCall(const FunctionDecl *Func);
516 static bool isFreeingOwnershipAttrCall(const CallEvent &Call);
517 static bool isAllocatingOwnershipAttrCall(const FunctionDecl *Func);
518 static bool isAllocatingOwnershipAttrCall(const CallEvent &Call);
519
520 friend class NoMemOwnershipChangeVisitor;
521
522 CallDescriptionMap<CheckFn> AllocaMemFnMap{
523 {{CDM::CLibrary, {"alloca"}, 1}, &MallocChecker::checkAlloca},
524 {{CDM::CLibrary, {"_alloca"}, 1}, &MallocChecker::checkAlloca},
525 // The line for "alloca" also covers "__builtin_alloca", but the
526 // _with_align variant must be listed separately because it takes an
527 // extra argument:
528 {{CDM::CLibrary, {"__builtin_alloca_with_align"}, 2},
529 &MallocChecker::checkAlloca},
530 };
531
532 CallDescriptionMap<CheckFn> AllocatingMemFnMap{
533 {{CDM::CLibrary, {"malloc"}, 1}, &MallocChecker::checkBasicAlloc},
534 {{CDM::CLibrary, {"malloc"}, 3}, &MallocChecker::checkKernelMalloc},
535 {{CDM::CLibrary, {"calloc"}, 2}, &MallocChecker::checkCalloc},
536 {{CDM::CLibrary, {"valloc"}, 1}, &MallocChecker::checkBasicAlloc},
537 {{CDM::CLibrary, {"strndup"}, 2}, &MallocChecker::checkStrdup},
538 {{CDM::CLibrary, {"strdup"}, 1}, &MallocChecker::checkStrdup},
539 {{CDM::CLibrary, {"_strdup"}, 1}, &MallocChecker::checkStrdup},
540 {{CDM::CLibrary, {"kmalloc"}, 2}, &MallocChecker::checkKernelMalloc},
541 {{CDM::CLibrary, {"if_nameindex"}, 1}, &MallocChecker::checkIfNameIndex},
542 {{CDM::CLibrary, {"wcsdup"}, 1}, &MallocChecker::checkStrdup},
543 {{CDM::CLibrary, {"_wcsdup"}, 1}, &MallocChecker::checkStrdup},
544 {{CDM::CLibrary, {"g_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
545 {{CDM::CLibrary, {"g_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
546 {{CDM::CLibrary, {"g_try_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
547 {{CDM::CLibrary, {"g_try_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
548 {{CDM::CLibrary, {"g_memdup"}, 2}, &MallocChecker::checkGMemdup},
549 {{CDM::CLibrary, {"g_malloc_n"}, 2}, &MallocChecker::checkGMallocN},
550 {{CDM::CLibrary, {"g_malloc0_n"}, 2}, &MallocChecker::checkGMallocN0},
551 {{CDM::CLibrary, {"g_try_malloc_n"}, 2}, &MallocChecker::checkGMallocN},
552 {{CDM::CLibrary, {"g_try_malloc0_n"}, 2}, &MallocChecker::checkGMallocN0},
553 };
554
555 CallDescriptionMap<CheckFn> ReallocatingMemFnMap{
556 {{CDM::CLibrary, {"realloc"}, 2},
557 std::bind(&MallocChecker::checkRealloc, _1, _2, _3, _4, false)},
558 {{CDM::CLibrary, {"reallocf"}, 2},
559 std::bind(&MallocChecker::checkRealloc, _1, _2, _3, _4, true)},
560 {{CDM::CLibrary, {"g_realloc"}, 2},
561 std::bind(&MallocChecker::checkRealloc, _1, _2, _3, _4, false)},
562 {{CDM::CLibrary, {"g_try_realloc"}, 2},
563 std::bind(&MallocChecker::checkRealloc, _1, _2, _3, _4, false)},
564 {{CDM::CLibrary, {"g_realloc_n"}, 3}, &MallocChecker::checkReallocN},
565 {{CDM::CLibrary, {"g_try_realloc_n"}, 3}, &MallocChecker::checkReallocN},
566 };
567
568 bool isMemCall(const CallEvent &Call) const;
569 bool hasOwnershipReturns(const CallEvent &Call) const;
570 bool hasOwnershipTakesHolds(const CallEvent &Call) const;
571 void reportTaintBug(StringRef Msg, ProgramStateRef State, CheckerContext &C,
572 llvm::ArrayRef<SymbolRef> TaintedSyms,
573 AllocationFamily Family) const;
574
575 void checkTaintedness(CheckerContext &C, const CallEvent &Call,
576 const SVal SizeSVal, ProgramStateRef State,
577 AllocationFamily Family) const;
578
579 // TODO: Remove mutable by moving the initializtaion to the registry function.
580 mutable std::optional<uint64_t> KernelZeroFlagVal;
581
582 using KernelZeroSizePtrValueTy = std::optional<int>;
583 /// Store the value of macro called `ZERO_SIZE_PTR`.
584 /// The value is initialized at first use, before first use the outer
585 /// Optional is empty, afterwards it contains another Optional that indicates
586 /// if the macro value could be determined, and if yes the value itself.
587 mutable std::optional<KernelZeroSizePtrValueTy> KernelZeroSizePtrValue;
588
589 /// Process C++ operator new()'s allocation, which is the part of C++
590 /// new-expression that goes before the constructor.
591 [[nodiscard]] ProgramStateRef
592 processNewAllocation(const CXXAllocatorCall &Call, CheckerContext &C,
593 AllocationFamily Family) const;
594
595 /// Perform a zero-allocation check.
596 ///
597 /// \param [in] Call The expression that allocates memory.
598 /// \param [in] IndexOfSizeArg Index of the argument that specifies the size
599 /// of the memory that needs to be allocated. E.g. for malloc, this would be
600 /// 0.
601 /// \param [in] RetVal Specifies the newly allocated pointer value;
602 /// if unspecified, the value of expression \p E is used.
603 [[nodiscard]] static ProgramStateRef
604 ProcessZeroAllocCheck(CheckerContext &C, const CallEvent &Call,
605 const unsigned IndexOfSizeArg, ProgramStateRef State,
606 std::optional<SVal> RetVal = std::nullopt);
607
608 /// Model functions with the ownership_returns attribute.
609 ///
610 /// User-defined function may have the ownership_returns attribute, which
611 /// annotates that the function returns with an object that was allocated on
612 /// the heap, and passes the ownertship to the callee.
613 ///
614 /// void __attribute((ownership_returns(malloc, 1))) *my_malloc(size_t);
615 ///
616 /// It has two parameters:
617 /// - first: name of the resource (e.g. 'malloc')
618 /// - (OPTIONAL) second: size of the allocated region
619 ///
620 /// \param [in] Call The expression that allocates memory.
621 /// \param [in] Att The ownership_returns attribute.
622 /// \param [in] State The \c ProgramState right before allocation.
623 /// \returns The ProgramState right after allocation.
624 [[nodiscard]] ProgramStateRef
625 MallocMemReturnsAttr(CheckerContext &C, const CallEvent &Call,
626 const OwnershipAttr *Att, ProgramStateRef State) const;
627 /// Models memory allocation.
628 ///
629 /// \param [in] C Checker context.
630 /// \param [in] Call The expression that allocates memory.
631 /// \param [in] State The \c ProgramState right before allocation.
632 /// \param [in] isAlloca Is the allocation function alloca-like
633 /// \returns The ProgramState with returnValue bound
634 [[nodiscard]] ProgramStateRef MallocBindRetVal(CheckerContext &C,
635 const CallEvent &Call,
636 ProgramStateRef State,
637 bool isAlloca) const;
638
639 /// Models memory allocation.
640 ///
641 /// \param [in] Call The expression that allocates memory.
642 /// \param [in] SizeEx Size of the memory that needs to be allocated.
643 /// \param [in] Init The value the allocated memory needs to be initialized.
644 /// with. For example, \c calloc initializes the allocated memory to 0,
645 /// malloc leaves it undefined.
646 /// \param [in] State The \c ProgramState right before allocation.
647 /// \returns The ProgramState right after allocation.
648 [[nodiscard]] ProgramStateRef
649 MallocMemAux(CheckerContext &C, const CallEvent &Call, const Expr *SizeEx,
650 SVal Init, ProgramStateRef State, AllocationFamily Family) const;
651
652 /// Models memory allocation.
653 ///
654 /// \param [in] Call The expression that allocates memory.
655 /// \param [in] Size Size of the memory that needs to be allocated.
656 /// \param [in] Init The value the allocated memory needs to be initialized.
657 /// with. For example, \c calloc initializes the allocated memory to 0,
658 /// malloc leaves it undefined.
659 /// \param [in] State The \c ProgramState right before allocation.
660 /// \returns The ProgramState right after allocation.
661 [[nodiscard]] ProgramStateRef MallocMemAux(CheckerContext &C,
662 const CallEvent &Call, SVal Size,
663 SVal Init, ProgramStateRef State,
664 AllocationFamily Family) const;
665
666 // Check if this malloc() for special flags. At present that means M_ZERO or
667 // __GFP_ZERO (in which case, treat it like calloc).
668 [[nodiscard]] std::optional<ProgramStateRef>
669 performKernelMalloc(const CallEvent &Call, CheckerContext &C,
670 const ProgramStateRef &State) const;
671
672 /// Model functions with the ownership_takes and ownership_holds attributes.
673 ///
674 /// User-defined function may have the ownership_takes and/or ownership_holds
675 /// attributes, which annotates that the function frees the memory passed as a
676 /// parameter.
677 ///
678 /// void __attribute((ownership_takes(malloc, 1))) my_free(void *);
679 /// void __attribute((ownership_holds(malloc, 1))) my_hold(void *);
680 ///
681 /// They have two parameters:
682 /// - first: name of the resource (e.g. 'malloc')
683 /// - second: index of the parameter the attribute applies to
684 ///
685 /// \param [in] Call The expression that frees memory.
686 /// \param [in] Att The ownership_takes or ownership_holds attribute.
687 /// \param [in] State The \c ProgramState right before allocation.
688 /// \returns The ProgramState right after deallocation.
689 [[nodiscard]] ProgramStateRef FreeMemAttr(CheckerContext &C,
690 const CallEvent &Call,
691 const OwnershipAttr *Att,
692 ProgramStateRef State) const;
693
694 /// Models memory deallocation.
695 ///
696 /// \param [in] Call The expression that frees memory.
697 /// \param [in] State The \c ProgramState right before allocation.
698 /// \param [in] Num Index of the argument that needs to be freed. This is
699 /// normally 0, but for custom free functions it may be different.
700 /// \param [in] Hold Whether the parameter at \p Index has the ownership_holds
701 /// attribute.
702 /// \param [out] IsKnownToBeAllocated Whether the memory to be freed is known
703 /// to have been allocated, or in other words, the symbol to be freed was
704 /// registered as allocated by this checker. In the following case, \c ptr
705 /// isn't known to be allocated.
706 /// void Haha(int *ptr) {
707 /// ptr = realloc(ptr, 67);
708 /// // ...
709 /// }
710 /// \param [in] ReturnsNullOnFailure Whether the memory deallocation function
711 /// we're modeling returns with Null on failure.
712 /// \returns The ProgramState right after deallocation.
713 [[nodiscard]] ProgramStateRef
714 FreeMemAux(CheckerContext &C, const CallEvent &Call, ProgramStateRef State,
715 unsigned Num, bool Hold, bool &IsKnownToBeAllocated,
716 AllocationFamily Family, bool ReturnsNullOnFailure = false) const;
717
718 /// Models memory deallocation.
719 ///
720 /// \param [in] ArgExpr The variable who's pointee needs to be freed.
721 /// \param [in] Call The expression that frees the memory.
722 /// \param [in] State The \c ProgramState right before allocation.
723 /// normally 0, but for custom free functions it may be different.
724 /// \param [in] Hold Whether the parameter at \p Index has the ownership_holds
725 /// attribute.
726 /// \param [out] IsKnownToBeAllocated Whether the memory to be freed is known
727 /// to have been allocated, or in other words, the symbol to be freed was
728 /// registered as allocated by this checker. In the following case, \c ptr
729 /// isn't known to be allocated.
730 /// void Haha(int *ptr) {
731 /// ptr = realloc(ptr, 67);
732 /// // ...
733 /// }
734 /// \param [in] ReturnsNullOnFailure Whether the memory deallocation function
735 /// we're modeling returns with Null on failure.
736 /// \param [in] ArgValOpt Optional value to use for the argument instead of
737 /// the one obtained from ArgExpr.
738 /// \returns The ProgramState right after deallocation.
739 [[nodiscard]] ProgramStateRef
740 FreeMemAux(CheckerContext &C, const Expr *ArgExpr, const CallEvent &Call,
741 ProgramStateRef State, bool Hold, bool &IsKnownToBeAllocated,
742 AllocationFamily Family, bool ReturnsNullOnFailure = false,
743 std::optional<SVal> ArgValOpt = {}) const;
744
745 // TODO: Needs some refactoring, as all other deallocation modeling
746 // functions are suffering from out parameters and messy code due to how
747 // realloc is handled.
748 //
749 /// Models memory reallocation.
750 ///
751 /// \param [in] Call The expression that reallocated memory
752 /// \param [in] ShouldFreeOnFail Whether if reallocation fails, the supplied
753 /// memory should be freed.
754 /// \param [in] State The \c ProgramState right before reallocation.
755 /// \param [in] SuffixWithN Whether the reallocation function we're modeling
756 /// has an '_n' suffix, such as g_realloc_n.
757 /// \returns The ProgramState right after reallocation.
758 [[nodiscard]] ProgramStateRef
759 ReallocMemAux(CheckerContext &C, const CallEvent &Call, bool ShouldFreeOnFail,
760 ProgramStateRef State, AllocationFamily Family,
761 bool SuffixWithN = false) const;
762
763 /// Evaluates the buffer size that needs to be allocated.
764 ///
765 /// \param [in] Blocks The amount of blocks that needs to be allocated.
766 /// \param [in] BlockBytes The size of a block.
767 /// \returns The symbolic value of \p Blocks * \p BlockBytes.
768 [[nodiscard]] static SVal evalMulForBufferSize(CheckerContext &C,
769 const Expr *Blocks,
770 const Expr *BlockBytes);
771
772 /// Models zero initialized array allocation.
773 ///
774 /// \param [in] Call The expression that reallocated memory
775 /// \param [in] State The \c ProgramState right before reallocation.
776 /// \returns The ProgramState right after allocation.
777 [[nodiscard]] ProgramStateRef CallocMem(CheckerContext &C,
778 const CallEvent &Call,
779 ProgramStateRef State) const;
780
781 /// See if deallocation happens in a suspicious context. If so, escape the
782 /// pointers that otherwise would have been deallocated and return true.
783 bool suppressDeallocationsInSuspiciousContexts(const CallEvent &Call,
784 CheckerContext &C) const;
785
786 /// If in \p S \p Sym is used, check whether \p Sym was already freed.
787 bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const;
788
789 /// If in \p S \p Sym is used, check whether \p Sym was allocated as a zero
790 /// sized memory region.
791 void checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
792 const Stmt *S) const;
793
794 /// Check if the function is known to free memory, or if it is
795 /// "interesting" and should be modeled explicitly.
796 ///
797 /// \param [out] EscapingSymbol A function might not free memory in general,
798 /// but could be known to free a particular symbol. In this case, false is
799 /// returned and the single escaping symbol is returned through the out
800 /// parameter.
801 ///
802 /// We assume that pointers do not escape through calls to system functions
803 /// not handled by this checker.
804 bool mayFreeAnyEscapedMemoryOrIsModeledExplicitly(const CallEvent *Call,
805 ProgramStateRef State,
806 SymbolRef &EscapingSymbol) const;
807
808 /// Implementation of the checkPointerEscape callbacks.
809 [[nodiscard]] ProgramStateRef
810 checkPointerEscapeAux(ProgramStateRef State,
811 const InvalidatedSymbols &Escaped,
812 const CallEvent *Call, PointerEscapeKind Kind,
813 bool IsConstPointerEscape) const;
814
815 // Implementation of the checkPreStmt and checkEndFunction callbacks.
816 void checkEscapeOnReturn(const ReturnStmt *S, CheckerContext &C) const;
817
818 ///@{
819 /// Returns a pointer to the checker frontend corresponding to the given
820 /// family or symbol. The template argument T may be either CheckerFamily or
821 /// a BUGTYPE_PROVIDER class; in the latter case the query is restricted to
822 /// frontends that descend from that PROVIDER class (i.e. can emit that bug
823 /// type). Note that this may return a frontend which is disabled.
824 template <class T>
825 const T *getRelevantFrontendAs(AllocationFamily Family) const;
826
827 template <class T>
828 const T *getRelevantFrontendAs(CheckerContext &C, SymbolRef Sym) const;
829 ///@}
830 static bool SummarizeValue(raw_ostream &os, SVal V);
831 static bool SummarizeRegion(ProgramStateRef State, raw_ostream &os,
832 const MemRegion *MR);
833
834 void HandleNonHeapDealloc(CheckerContext &C, SVal ArgVal, SourceRange Range,
835 const Expr *DeallocExpr,
836 AllocationFamily Family) const;
837
838 void HandleFreeAlloca(CheckerContext &C, SVal ArgVal,
839 SourceRange Range) const;
840
841 void HandleMismatchedDealloc(CheckerContext &C, SourceRange Range,
842 const Expr *DeallocExpr, const RefState *RS,
843 SymbolRef Sym, bool OwnershipTransferred) const;
844
845 void HandleOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
846 const Expr *DeallocExpr, AllocationFamily Family,
847 const Expr *AllocExpr = nullptr) const;
848
849 void HandleUseAfterFree(CheckerContext &C, SourceRange Range,
850 SymbolRef Sym) const;
851
852 void HandleDoubleFree(CheckerContext &C, SourceRange Range, bool Released,
853 SymbolRef Sym, SymbolRef PrevSym) const;
854
855 void HandleUseZeroAlloc(CheckerContext &C, SourceRange Range,
856 SymbolRef Sym) const;
857
858 void HandleFunctionPtrFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
859 const Expr *FreeExpr,
860 AllocationFamily Family) const;
861
862 /// Find the location of the allocation for Sym on the path leading to the
863 /// exploded node N.
864 static LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
865 CheckerContext &C);
866
867 void HandleLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const;
868
869 /// Test if value in ArgVal equals to value in macro `ZERO_SIZE_PTR`.
870 bool isArgZERO_SIZE_PTR(ProgramStateRef State, CheckerContext &C,
871 SVal ArgVal) const;
872};
873} // end anonymous namespace
874
875//===----------------------------------------------------------------------===//
876// Definition of NoOwnershipChangeVisitor.
877//===----------------------------------------------------------------------===//
878
879namespace {
880class NoMemOwnershipChangeVisitor final : public NoOwnershipChangeVisitor {
881protected:
882 /// Syntactically checks whether the callee is a deallocating function. Since
883 /// we have no path-sensitive information on this call (we would need a
884 /// CallEvent instead of a CallExpr for that), its possible that a
885 /// deallocation function was called indirectly through a function pointer,
886 /// but we are not able to tell, so this is a best effort analysis.
887 /// See namespace `memory_passed_to_fn_call_free_through_fn_ptr` in
888 /// clang/test/Analysis/NewDeleteLeaks.cpp.
889 bool isFreeingCallAsWritten(const CallExpr &Call) const {
890 const auto *MallocChk = static_cast<const MallocChecker *>(&Checker);
891 if (MallocChk->FreeingMemFnMap.lookupAsWritten(Call) ||
892 MallocChk->ReallocatingMemFnMap.lookupAsWritten(Call))
893 return true;
894
895 if (const auto *Func =
896 llvm::dyn_cast_or_null<FunctionDecl>(Call.getCalleeDecl()))
897 return MallocChecker::isFreeingOwnershipAttrCall(Func);
898
899 return false;
900 }
901
902 bool hasResourceStateChanged(ProgramStateRef CallEnterState,
903 ProgramStateRef CallExitEndState) final {
904 return CallEnterState->get<RegionState>(Sym) !=
905 CallExitEndState->get<RegionState>(Sym);
906 }
907
908 /// Heuristically guess whether the callee intended to free memory. This is
909 /// done syntactically, because we are trying to argue about alternative
910 /// paths of execution, and as a consequence we don't have path-sensitive
911 /// information.
912 bool doesFnIntendToHandleOwnership(const Decl *Callee,
913 ASTContext &ACtx) final {
914 const FunctionDecl *FD = dyn_cast<FunctionDecl>(Callee);
915
916 // Given that the stack frame was entered, the body should always be
917 // theoretically obtainable. In case of body farms, the synthesized body
918 // is not attached to declaration, thus triggering the '!FD->hasBody()'
919 // branch. That said, would a synthesized body ever intend to handle
920 // ownership? As of today they don't. And if they did, how would we
921 // put notes inside it, given that it doesn't match any source locations?
922 if (!FD || !FD->hasBody())
923 return false;
924 using namespace clang::ast_matchers;
925
926 auto Matches = match(findAll(stmt(anyOf(cxxDeleteExpr().bind("delete"),
927 callExpr().bind("call")))),
928 *FD->getBody(), ACtx);
929 for (BoundNodes Match : Matches) {
930 if (Match.getNodeAs<CXXDeleteExpr>("delete"))
931 return true;
932
933 if (const auto *Call = Match.getNodeAs<CallExpr>("call"))
934 if (isFreeingCallAsWritten(*Call))
935 return true;
936 }
937 // TODO: Ownership might change with an attempt to store the allocated
938 // memory, not only through deallocation. Check for attempted stores as
939 // well.
940 return false;
941 }
942
943 PathDiagnosticPieceRef emitNote(const ExplodedNode *N) final {
944 PathDiagnosticLocation L = PathDiagnosticLocation::create(
945 N->getLocation(),
946 N->getState()->getStateManager().getContext().getSourceManager());
947 return std::make_shared<PathDiagnosticEventPiece>(
948 L, "Returning without deallocating memory or storing the pointer for "
949 "later deallocation");
950 }
951
952public:
953 NoMemOwnershipChangeVisitor(SymbolRef Sym, const MallocChecker *Checker)
954 : NoOwnershipChangeVisitor(Sym, Checker) {}
955
956 void Profile(llvm::FoldingSetNodeID &ID) const override {
957 static int Tag = 0;
958 ID.AddPointer(&Tag);
959 ID.AddPointer(Sym);
960 }
961};
962
963} // end anonymous namespace
964
965//===----------------------------------------------------------------------===//
966// Definition of MallocBugVisitor.
967//===----------------------------------------------------------------------===//
968
969namespace {
970/// The bug visitor which allows us to print extra diagnostics along the
971/// BugReport path. For example, showing the allocation site of the leaked
972/// region.
973class MallocBugVisitor final : public BugReporterVisitor {
974protected:
975 enum NotificationMode { Normal, ReallocationFailed };
976
977 // The allocated region symbol tracked by the main analysis.
978 SymbolRef Sym;
979
980 // The mode we are in, i.e. what kind of diagnostics will be emitted.
981 NotificationMode Mode;
982
983 // A symbol from when the primary region should have been reallocated.
984 SymbolRef FailedReallocSymbol;
985
986 // A release function stack frame in which memory was released. Used for
987 // miscellaneous false positive suppression.
988 const StackFrameContext *ReleaseFunctionLC;
989
990 bool IsLeak;
991
992public:
993 MallocBugVisitor(SymbolRef S, bool isLeak = false)
994 : Sym(S), Mode(Normal), FailedReallocSymbol(nullptr),
995 ReleaseFunctionLC(nullptr), IsLeak(isLeak) {}
996
997 static void *getTag() {
998 static int Tag = 0;
999 return &Tag;
1000 }
1001
1002 void Profile(llvm::FoldingSetNodeID &ID) const override {
1003 ID.AddPointer(getTag());
1004 ID.AddPointer(Sym);
1005 }
1006
1007 /// Did not track -> allocated. Other state (released) -> allocated.
1008 static inline bool isAllocated(const RefState *RSCurr, const RefState *RSPrev,
1009 const Stmt *Stmt) {
1010 return (isa_and_nonnull<CallExpr, CXXNewExpr>(Stmt) &&
1011 (RSCurr &&
1012 (RSCurr->isAllocated() || RSCurr->isAllocatedOfSizeZero())) &&
1013 (!RSPrev ||
1014 !(RSPrev->isAllocated() || RSPrev->isAllocatedOfSizeZero())));
1015 }
1016
1017 /// Did not track -> released. Other state (allocated) -> released.
1018 /// The statement associated with the release might be missing.
1019 static inline bool isReleased(const RefState *RSCurr, const RefState *RSPrev,
1020 const Stmt *Stmt) {
1021 bool IsReleased =
1022 (RSCurr && RSCurr->isReleased()) && (!RSPrev || !RSPrev->isReleased());
1023 assert(!IsReleased || (isa_and_nonnull<CallExpr, CXXDeleteExpr>(Stmt)) ||
1024 (!Stmt && RSCurr->getAllocationFamily().Kind == AF_InnerBuffer));
1025 return IsReleased;
1026 }
1027
1028 /// Did not track -> relinquished. Other state (allocated) -> relinquished.
1029 static inline bool isRelinquished(const RefState *RSCurr,
1030 const RefState *RSPrev, const Stmt *Stmt) {
1031 return (
1032 isa_and_nonnull<CallExpr, ObjCMessageExpr, ObjCPropertyRefExpr>(Stmt) &&
1033 (RSCurr && RSCurr->isRelinquished()) &&
1034 (!RSPrev || !RSPrev->isRelinquished()));
1035 }
1036
1037 /// If the expression is not a call, and the state change is
1038 /// released -> allocated, it must be the realloc return value
1039 /// check. If we have to handle more cases here, it might be cleaner just
1040 /// to track this extra bit in the state itself.
1041 static inline bool hasReallocFailed(const RefState *RSCurr,
1042 const RefState *RSPrev,
1043 const Stmt *Stmt) {
1044 return ((!isa_and_nonnull<CallExpr>(Stmt)) &&
1045 (RSCurr &&
1046 (RSCurr->isAllocated() || RSCurr->isAllocatedOfSizeZero())) &&
1047 (RSPrev &&
1048 !(RSPrev->isAllocated() || RSPrev->isAllocatedOfSizeZero())));
1049 }
1050
1051 PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
1052 BugReporterContext &BRC,
1053 PathSensitiveBugReport &BR) override;
1054
1055 PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
1056 const ExplodedNode *EndPathNode,
1057 PathSensitiveBugReport &BR) override {
1058 if (!IsLeak)
1059 return nullptr;
1060
1061 PathDiagnosticLocation L = BR.getLocation();
1062 // Do not add the statement itself as a range in case of leak.
1063 return std::make_shared<PathDiagnosticEventPiece>(L, BR.getDescription(),
1064 false);
1065 }
1066
1067private:
1068 class StackHintGeneratorForReallocationFailed
1069 : public StackHintGeneratorForSymbol {
1070 public:
1071 StackHintGeneratorForReallocationFailed(SymbolRef S, StringRef M)
1072 : StackHintGeneratorForSymbol(S, M) {}
1073
1074 std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex) override {
1075 // Printed parameters start at 1, not 0.
1076 ++ArgIndex;
1077
1078 SmallString<200> buf;
1079 llvm::raw_svector_ostream os(buf);
1080
1081 os << "Reallocation of " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
1082 << " parameter failed";
1083
1084 return std::string(os.str());
1085 }
1086
1087 std::string getMessageForReturn(const CallExpr *CallExpr) override {
1088 return "Reallocation of returned value failed";
1089 }
1090 };
1091};
1092} // end anonymous namespace
1093
1094// A map from the freed symbol to the symbol representing the return value of
1095// the free function.
1097
1098namespace {
1099class StopTrackingCallback final : public SymbolVisitor {
1100 ProgramStateRef state;
1101
1102public:
1103 StopTrackingCallback(ProgramStateRef st) : state(std::move(st)) {}
1104 ProgramStateRef getState() const { return state; }
1105
1106 bool VisitSymbol(SymbolRef sym) override {
1107 state = state->remove<RegionState>(sym);
1108 return true;
1109 }
1110};
1111
1112/// EscapeTrackedCallback - A SymbolVisitor that marks allocated symbols as
1113/// escaped.
1114///
1115/// This visitor is used to suppress false positive leak reports when smart
1116/// pointers are nested in temporary objects passed by value to functions. When
1117/// the analyzer can't see the destructor calls for temporary objects, it may
1118/// incorrectly report leaks for memory that will be properly freed by the smart
1119/// pointer destructors.
1120///
1121/// The visitor traverses reachable symbols from a given set of memory regions
1122/// (typically smart pointer field regions) and marks any allocated symbols as
1123/// escaped. Escaped symbols are not reported as leaks by checkDeadSymbols.
1124class EscapeTrackedCallback final : public SymbolVisitor {
1125 ProgramStateRef State;
1126
1127 explicit EscapeTrackedCallback(ProgramStateRef S) : State(std::move(S)) {}
1128
1129public:
1130 bool VisitSymbol(SymbolRef Sym) override {
1131 if (const RefState *RS = State->get<RegionState>(Sym)) {
1132 if (RS->isAllocated() || RS->isAllocatedOfSizeZero()) {
1133 State = State->set<RegionState>(Sym, RefState::getEscaped(RS));
1134 }
1135 }
1136 return true;
1137 }
1138
1139 /// Escape tracked regions reachable from the given roots.
1140 static ProgramStateRef
1141 EscapeTrackedRegionsReachableFrom(ArrayRef<const MemRegion *> Roots,
1142 ProgramStateRef State) {
1143 if (Roots.empty())
1144 return State;
1145
1146 // scanReachableSymbols is expensive, so we use a single visitor for all
1147 // roots
1148 SmallVector<const MemRegion *, 10> Regions;
1149 EscapeTrackedCallback Visitor(State);
1150 for (const MemRegion *R : Roots) {
1151 Regions.push_back(R);
1152 }
1153 State->scanReachableSymbols(Regions, Visitor);
1154 return Visitor.State;
1155 }
1156
1157 friend class SymbolVisitor;
1158};
1159} // end anonymous namespace
1160
1161static bool isStandardNew(const FunctionDecl *FD) {
1162 if (!FD)
1163 return false;
1164
1166 if (Kind != OO_New && Kind != OO_Array_New)
1167 return false;
1168
1169 // This is standard if and only if it's not defined in a user file.
1170 SourceLocation L = FD->getLocation();
1171 // If the header for operator delete is not included, it's still defined
1172 // in an invalid source location. Check to make sure we don't crash.
1173 return !L.isValid() ||
1175}
1176
1177static bool isStandardDelete(const FunctionDecl *FD) {
1178 if (!FD)
1179 return false;
1180
1182 if (Kind != OO_Delete && Kind != OO_Array_Delete)
1183 return false;
1184
1185 bool HasBody = FD->hasBody(); // Prefer using the definition.
1186
1187 // This is standard if and only if it's not defined in a user file.
1188 SourceLocation L = FD->getLocation();
1189
1190 // If the header for operator delete is not included, it's still defined
1191 // in an invalid source location. Check to make sure we don't crash.
1192 const auto &SM = FD->getASTContext().getSourceManager();
1193 return L.isInvalid() || (!HasBody && SM.isInSystemHeader(L));
1194}
1195
1196//===----------------------------------------------------------------------===//
1197// Methods of MallocChecker and MallocBugVisitor.
1198//===----------------------------------------------------------------------===//
1199
1200bool MallocChecker::isFreeingOwnershipAttrCall(const CallEvent &Call) {
1201 const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
1202
1203 return Func && isFreeingOwnershipAttrCall(Func);
1204}
1205
1206bool MallocChecker::isFreeingOwnershipAttrCall(const FunctionDecl *Func) {
1207 if (Func->hasAttrs()) {
1208 for (const auto *I : Func->specific_attrs<OwnershipAttr>()) {
1209 OwnershipAttr::OwnershipKind OwnKind = I->getOwnKind();
1210 if (OwnKind == OwnershipAttr::Takes || OwnKind == OwnershipAttr::Holds)
1211 return true;
1212 }
1213 }
1214 return false;
1215}
1216
1217bool MallocChecker::isFreeingCall(const CallEvent &Call) const {
1218 if (FreeingMemFnMap.lookup(Call) || ReallocatingMemFnMap.lookup(Call))
1219 return true;
1220
1221 return isFreeingOwnershipAttrCall(Call);
1222}
1223
1224bool MallocChecker::isAllocatingOwnershipAttrCall(const CallEvent &Call) {
1225 const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
1226
1227 return Func && isAllocatingOwnershipAttrCall(Func);
1228}
1229
1230bool MallocChecker::isAllocatingOwnershipAttrCall(const FunctionDecl *Func) {
1231 for (const auto *I : Func->specific_attrs<OwnershipAttr>()) {
1232 if (I->getOwnKind() == OwnershipAttr::Returns)
1233 return true;
1234 }
1235
1236 return false;
1237}
1238
1239bool MallocChecker::isMemCall(const CallEvent &Call) const {
1240 if (FreeingMemFnMap.lookup(Call) || AllocatingMemFnMap.lookup(Call) ||
1241 AllocaMemFnMap.lookup(Call) || ReallocatingMemFnMap.lookup(Call))
1242 return true;
1243
1244 if (!ShouldIncludeOwnershipAnnotatedFunctions)
1245 return false;
1246
1247 const auto *Func = dyn_cast<FunctionDecl>(Call.getDecl());
1248 return Func && Func->hasAttr<OwnershipAttr>();
1249}
1250
1251std::optional<ProgramStateRef>
1252MallocChecker::performKernelMalloc(const CallEvent &Call, CheckerContext &C,
1253 const ProgramStateRef &State) const {
1254 // 3-argument malloc(), as commonly used in {Free,Net,Open}BSD Kernels:
1255 //
1256 // void *malloc(unsigned long size, struct malloc_type *mtp, int flags);
1257 //
1258 // One of the possible flags is M_ZERO, which means 'give me back an
1259 // allocation which is already zeroed', like calloc.
1260
1261 // 2-argument kmalloc(), as used in the Linux kernel:
1262 //
1263 // void *kmalloc(size_t size, gfp_t flags);
1264 //
1265 // Has the similar flag value __GFP_ZERO.
1266
1267 // This logic is largely cloned from O_CREAT in UnixAPIChecker, maybe some
1268 // code could be shared.
1269
1270 ASTContext &Ctx = C.getASTContext();
1271 llvm::Triple::OSType OS = Ctx.getTargetInfo().getTriple().getOS();
1272
1273 if (!KernelZeroFlagVal) {
1274 switch (OS) {
1275 case llvm::Triple::FreeBSD:
1276 KernelZeroFlagVal = 0x0100;
1277 break;
1278 case llvm::Triple::NetBSD:
1279 KernelZeroFlagVal = 0x0002;
1280 break;
1281 case llvm::Triple::OpenBSD:
1282 KernelZeroFlagVal = 0x0008;
1283 break;
1284 case llvm::Triple::Linux:
1285 // __GFP_ZERO
1286 KernelZeroFlagVal = 0x8000;
1287 break;
1288 default:
1289 // FIXME: We need a more general way of getting the M_ZERO value.
1290 // See also: O_CREAT in UnixAPIChecker.cpp.
1291
1292 // Fall back to normal malloc behavior on platforms where we don't
1293 // know M_ZERO.
1294 return std::nullopt;
1295 }
1296 }
1297
1298 // We treat the last argument as the flags argument, and callers fall-back to
1299 // normal malloc on a None return. This works for the FreeBSD kernel malloc
1300 // as well as Linux kmalloc.
1301 if (Call.getNumArgs() < 2)
1302 return std::nullopt;
1303
1304 const Expr *FlagsEx = Call.getArgExpr(Call.getNumArgs() - 1);
1305 const SVal V = C.getSVal(FlagsEx);
1306 if (!isa<NonLoc>(V)) {
1307 // The case where 'V' can be a location can only be due to a bad header,
1308 // so in this case bail out.
1309 return std::nullopt;
1310 }
1311
1312 NonLoc Flags = V.castAs<NonLoc>();
1313 NonLoc ZeroFlag = C.getSValBuilder()
1314 .makeIntVal(*KernelZeroFlagVal, FlagsEx->getType())
1315 .castAs<NonLoc>();
1316 SVal MaskedFlagsUC = C.getSValBuilder().evalBinOpNN(State, BO_And,
1317 Flags, ZeroFlag,
1318 FlagsEx->getType());
1319 if (MaskedFlagsUC.isUnknownOrUndef())
1320 return std::nullopt;
1321 DefinedSVal MaskedFlags = MaskedFlagsUC.castAs<DefinedSVal>();
1322
1323 // Check if maskedFlags is non-zero.
1324 ProgramStateRef TrueState, FalseState;
1325 std::tie(TrueState, FalseState) = State->assume(MaskedFlags);
1326
1327 // If M_ZERO is set, treat this like calloc (initialized).
1328 if (TrueState && !FalseState) {
1329 SVal ZeroVal = C.getSValBuilder().makeZeroVal(Ctx.CharTy);
1330 return MallocMemAux(C, Call, Call.getArgExpr(0), ZeroVal, TrueState,
1331 AllocationFamily(AF_Malloc));
1332 }
1333
1334 return std::nullopt;
1335}
1336
1337SVal MallocChecker::evalMulForBufferSize(CheckerContext &C, const Expr *Blocks,
1338 const Expr *BlockBytes) {
1339 SValBuilder &SB = C.getSValBuilder();
1340 SVal BlocksVal = C.getSVal(Blocks);
1341 SVal BlockBytesVal = C.getSVal(BlockBytes);
1342 ProgramStateRef State = C.getState();
1343 SVal TotalSize = SB.evalBinOp(State, BO_Mul, BlocksVal, BlockBytesVal,
1345 return TotalSize;
1346}
1347
1348void MallocChecker::checkBasicAlloc(ProgramStateRef State,
1349 const CallEvent &Call,
1350 CheckerContext &C) const {
1351 State = MallocMemAux(C, Call, Call.getArgExpr(0), UndefinedVal(), State,
1352 AllocationFamily(AF_Malloc));
1353 State = ProcessZeroAllocCheck(C, Call, 0, State);
1354 C.addTransition(State);
1355}
1356
1357void MallocChecker::checkKernelMalloc(ProgramStateRef State,
1358 const CallEvent &Call,
1359 CheckerContext &C) const {
1360 std::optional<ProgramStateRef> MaybeState =
1361 performKernelMalloc(Call, C, State);
1362 if (MaybeState)
1363 State = *MaybeState;
1364 else
1365 State = MallocMemAux(C, Call, Call.getArgExpr(0), UndefinedVal(), State,
1366 AllocationFamily(AF_Malloc));
1367 C.addTransition(State);
1368}
1369
1370static bool isStandardRealloc(const CallEvent &Call) {
1371 const FunctionDecl *FD = dyn_cast<FunctionDecl>(Call.getDecl());
1372 assert(FD);
1373 ASTContext &AC = FD->getASTContext();
1374 return AC.hasSameType(FD->getDeclaredReturnType(), AC.VoidPtrTy) &&
1375 AC.hasSameType(FD->getParamDecl(0)->getType(), AC.VoidPtrTy) &&
1376 AC.hasSameType(FD->getParamDecl(1)->getType(), AC.getSizeType());
1377}
1378
1379static bool isGRealloc(const CallEvent &Call) {
1380 const FunctionDecl *FD = dyn_cast<FunctionDecl>(Call.getDecl());
1381 assert(FD);
1382 ASTContext &AC = FD->getASTContext();
1383
1384 return AC.hasSameType(FD->getDeclaredReturnType(), AC.VoidPtrTy) &&
1385 AC.hasSameType(FD->getParamDecl(0)->getType(), AC.VoidPtrTy) &&
1387}
1388
1389void MallocChecker::checkRealloc(ProgramStateRef State, const CallEvent &Call,
1390 CheckerContext &C,
1391 bool ShouldFreeOnFail) const {
1392 // Ignore calls to functions whose type does not match the expected type of
1393 // either the standard realloc or g_realloc from GLib.
1394 // FIXME: Should we perform this kind of checking consistently for each
1395 // function? If yes, then perhaps extend the `CallDescription` interface to
1396 // handle this.
1398 return;
1399
1400 State = ReallocMemAux(C, Call, ShouldFreeOnFail, State,
1401 AllocationFamily(AF_Malloc));
1402 State = ProcessZeroAllocCheck(C, Call, 1, State);
1403 C.addTransition(State);
1404}
1405
1406void MallocChecker::checkCalloc(ProgramStateRef State, const CallEvent &Call,
1407 CheckerContext &C) const {
1408 State = CallocMem(C, Call, State);
1409 State = ProcessZeroAllocCheck(C, Call, 0, State);
1410 State = ProcessZeroAllocCheck(C, Call, 1, State);
1411 C.addTransition(State);
1412}
1413
1414void MallocChecker::checkFree(ProgramStateRef State, const CallEvent &Call,
1415 CheckerContext &C) const {
1416 bool IsKnownToBeAllocatedMemory = false;
1417 if (suppressDeallocationsInSuspiciousContexts(Call, C))
1418 return;
1419 State = FreeMemAux(C, Call, State, 0, false, IsKnownToBeAllocatedMemory,
1420 AllocationFamily(AF_Malloc));
1421 C.addTransition(State);
1422}
1423
1424void MallocChecker::checkAlloca(ProgramStateRef State, const CallEvent &Call,
1425 CheckerContext &C) const {
1426 State = MallocMemAux(C, Call, Call.getArgExpr(0), UndefinedVal(), State,
1427 AllocationFamily(AF_Alloca));
1428 State = ProcessZeroAllocCheck(C, Call, 0, State);
1429 C.addTransition(State);
1430}
1431
1432void MallocChecker::checkStrdup(ProgramStateRef State, const CallEvent &Call,
1433 CheckerContext &C) const {
1434 const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
1435 if (!CE)
1436 return;
1437 State = MallocMemAux(C, Call, UnknownVal(), UnknownVal(), State,
1438 AllocationFamily(AF_Malloc));
1439
1440 C.addTransition(State);
1441}
1442
1443void MallocChecker::checkIfNameIndex(ProgramStateRef State,
1444 const CallEvent &Call,
1445 CheckerContext &C) const {
1446 // Should we model this differently? We can allocate a fixed number of
1447 // elements with zeros in the last one.
1448 State = MallocMemAux(C, Call, UnknownVal(), UnknownVal(), State,
1449 AllocationFamily(AF_IfNameIndex));
1450
1451 C.addTransition(State);
1452}
1453
1454void MallocChecker::checkIfFreeNameIndex(ProgramStateRef State,
1455 const CallEvent &Call,
1456 CheckerContext &C) const {
1457 bool IsKnownToBeAllocatedMemory = false;
1458 State = FreeMemAux(C, Call, State, 0, false, IsKnownToBeAllocatedMemory,
1459 AllocationFamily(AF_IfNameIndex));
1460 C.addTransition(State);
1461}
1462
1464 const FunctionDecl *FD) {
1465 // Checking for signature:
1466 // void* operator new ( std::size_t count, void* ptr );
1467 // void* operator new[]( std::size_t count, void* ptr );
1468 if (CE->getNumArgs() != 2 || (FD->getOverloadedOperator() != OO_New &&
1469 FD->getOverloadedOperator() != OO_Array_New))
1470 return nullptr;
1471 auto BuffType = FD->getParamDecl(1)->getType();
1472 if (BuffType.isNull() || !BuffType->isVoidPointerType())
1473 return nullptr;
1474 return CE->getArg(1);
1475}
1476
1477void MallocChecker::checkCXXNewOrCXXDelete(ProgramStateRef State,
1478 const CallEvent &Call,
1479 CheckerContext &C) const {
1480 bool IsKnownToBeAllocatedMemory = false;
1481 const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
1482 if (!CE)
1483 return;
1484
1485 assert(isStandardNewDelete(Call));
1486
1487 // Process direct calls to operator new/new[]/delete/delete[] functions
1488 // as distinct from new/new[]/delete/delete[] expressions that are
1489 // processed by the checkPostStmt callbacks for CXXNewExpr and
1490 // CXXDeleteExpr.
1491 const FunctionDecl *FD = C.getCalleeDecl(CE);
1492 if (const auto *BufArg = getPlacementNewBufferArg(CE, FD)) {
1493 // Placement new does not allocate memory
1494 auto RetVal = State->getSVal(BufArg, Call.getLocationContext());
1495 State = State->BindExpr(CE, C.getLocationContext(), RetVal);
1496 C.addTransition(State);
1497 return;
1498 }
1499
1500 switch (FD->getOverloadedOperator()) {
1501 case OO_New:
1502 State = MallocMemAux(C, Call, CE->getArg(0), UndefinedVal(), State,
1503 AllocationFamily(AF_CXXNew));
1504 State = ProcessZeroAllocCheck(C, Call, 0, State);
1505 break;
1506 case OO_Array_New:
1507 State = MallocMemAux(C, Call, CE->getArg(0), UndefinedVal(), State,
1508 AllocationFamily(AF_CXXNewArray));
1509 State = ProcessZeroAllocCheck(C, Call, 0, State);
1510 break;
1511 case OO_Delete:
1512 State = FreeMemAux(C, Call, State, 0, false, IsKnownToBeAllocatedMemory,
1513 AllocationFamily(AF_CXXNew));
1514 break;
1515 case OO_Array_Delete:
1516 State = FreeMemAux(C, Call, State, 0, false, IsKnownToBeAllocatedMemory,
1517 AllocationFamily(AF_CXXNewArray));
1518 break;
1519 default:
1520 assert(false && "not a new/delete operator");
1521 return;
1522 }
1523
1524 C.addTransition(State);
1525}
1526
1527void MallocChecker::checkGMalloc0(ProgramStateRef State, const CallEvent &Call,
1528 CheckerContext &C) const {
1529 SValBuilder &svalBuilder = C.getSValBuilder();
1530 SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
1531 State = MallocMemAux(C, Call, Call.getArgExpr(0), zeroVal, State,
1532 AllocationFamily(AF_Malloc));
1533 State = ProcessZeroAllocCheck(C, Call, 0, State);
1534 C.addTransition(State);
1535}
1536
1537void MallocChecker::checkGMemdup(ProgramStateRef State, const CallEvent &Call,
1538 CheckerContext &C) const {
1539 State = MallocMemAux(C, Call, Call.getArgExpr(1), UnknownVal(), State,
1540 AllocationFamily(AF_Malloc));
1541 State = ProcessZeroAllocCheck(C, Call, 1, State);
1542 C.addTransition(State);
1543}
1544
1545void MallocChecker::checkGMallocN(ProgramStateRef State, const CallEvent &Call,
1546 CheckerContext &C) const {
1547 SVal Init = UndefinedVal();
1548 SVal TotalSize = evalMulForBufferSize(C, Call.getArgExpr(0), Call.getArgExpr(1));
1549 State = MallocMemAux(C, Call, TotalSize, Init, State,
1550 AllocationFamily(AF_Malloc));
1551 State = ProcessZeroAllocCheck(C, Call, 0, State);
1552 State = ProcessZeroAllocCheck(C, Call, 1, State);
1553 C.addTransition(State);
1554}
1555
1556void MallocChecker::checkGMallocN0(ProgramStateRef State, const CallEvent &Call,
1557 CheckerContext &C) const {
1558 SValBuilder &SB = C.getSValBuilder();
1559 SVal Init = SB.makeZeroVal(SB.getContext().CharTy);
1560 SVal TotalSize = evalMulForBufferSize(C, Call.getArgExpr(0), Call.getArgExpr(1));
1561 State = MallocMemAux(C, Call, TotalSize, Init, State,
1562 AllocationFamily(AF_Malloc));
1563 State = ProcessZeroAllocCheck(C, Call, 0, State);
1564 State = ProcessZeroAllocCheck(C, Call, 1, State);
1565 C.addTransition(State);
1566}
1567
1568static bool isFromStdNamespace(const CallEvent &Call) {
1569 const Decl *FD = Call.getDecl();
1570 assert(FD && "a CallDescription cannot match a call without a Decl");
1571 return FD->isInStdNamespace();
1572}
1573
1574void MallocChecker::preGetDelimOrGetLine(ProgramStateRef State,
1575 const CallEvent &Call,
1576 CheckerContext &C) const {
1577 // Discard calls to the C++ standard library function std::getline(), which
1578 // is completely unrelated to the POSIX getline() that we're checking.
1580 return;
1581
1582 const auto LinePtr = getPointeeVal(Call.getArgSVal(0), State);
1583 if (!LinePtr)
1584 return;
1585
1586 // FreeMemAux takes IsKnownToBeAllocated as an output parameter, and it will
1587 // be true after the call if the symbol was registered by this checker.
1588 // We do not need this value here, as FreeMemAux will take care
1589 // of reporting any violation of the preconditions.
1590 bool IsKnownToBeAllocated = false;
1591 State = FreeMemAux(C, Call.getArgExpr(0), Call, State, false,
1592 IsKnownToBeAllocated, AllocationFamily(AF_Malloc), false,
1593 LinePtr);
1594 if (State)
1595 C.addTransition(State);
1596}
1597
1598void MallocChecker::checkGetDelimOrGetLine(ProgramStateRef State,
1599 const CallEvent &Call,
1600 CheckerContext &C) const {
1601 // Discard calls to the C++ standard library function std::getline(), which
1602 // is completely unrelated to the POSIX getline() that we're checking.
1604 return;
1605
1606 // Handle the post-conditions of getline and getdelim:
1607 // Register the new conjured value as an allocated buffer.
1608 const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
1609 if (!CE)
1610 return;
1611
1612 const auto LinePtrOpt = getPointeeVal(Call.getArgSVal(0), State);
1613 const auto SizeOpt = getPointeeVal(Call.getArgSVal(1), State);
1614 if (!LinePtrOpt || !SizeOpt || LinePtrOpt->isUnknownOrUndef() ||
1615 SizeOpt->isUnknownOrUndef())
1616 return;
1617
1618 const auto LinePtr = LinePtrOpt->getAs<DefinedSVal>();
1619 const auto Size = SizeOpt->getAs<DefinedSVal>();
1620 const MemRegion *LinePtrReg = LinePtr->getAsRegion();
1621 if (!LinePtrReg)
1622 return;
1623
1624 State = setDynamicExtent(State, LinePtrReg, *Size);
1625 C.addTransition(MallocUpdateRefState(C, CE, State,
1626 AllocationFamily(AF_Malloc), *LinePtr));
1627}
1628
1629void MallocChecker::checkReallocN(ProgramStateRef State, const CallEvent &Call,
1630 CheckerContext &C) const {
1631 State = ReallocMemAux(C, Call, /*ShouldFreeOnFail=*/false, State,
1632 AllocationFamily(AF_Malloc),
1633 /*SuffixWithN=*/true);
1634 State = ProcessZeroAllocCheck(C, Call, 1, State);
1635 State = ProcessZeroAllocCheck(C, Call, 2, State);
1636 C.addTransition(State);
1637}
1638
1639void MallocChecker::checkOwnershipAttr(ProgramStateRef State,
1640 const CallEvent &Call,
1641 CheckerContext &C) const {
1642 const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
1643 if (!CE)
1644 return;
1645 const FunctionDecl *FD = C.getCalleeDecl(CE);
1646 if (!FD)
1647 return;
1648 if (ShouldIncludeOwnershipAnnotatedFunctions ||
1649 MismatchedDeallocatorChecker.isEnabled()) {
1650 // Check all the attributes, if there are any.
1651 // There can be multiple of these attributes.
1652 if (FD->hasAttrs())
1653 for (const auto *I : FD->specific_attrs<OwnershipAttr>()) {
1654 switch (I->getOwnKind()) {
1655 case OwnershipAttr::Returns:
1656 State = MallocMemReturnsAttr(C, Call, I, State);
1657 break;
1658 case OwnershipAttr::Takes:
1659 case OwnershipAttr::Holds:
1660 State = FreeMemAttr(C, Call, I, State);
1661 break;
1662 }
1663 }
1664 }
1665 C.addTransition(State);
1666}
1667
1668bool MallocChecker::evalCall(const CallEvent &Call, CheckerContext &C) const {
1669 if (!Call.getOriginExpr())
1670 return false;
1671
1672 ProgramStateRef State = C.getState();
1673
1674 if (const CheckFn *Callback = FreeingMemFnMap.lookup(Call)) {
1675 (*Callback)(this, State, Call, C);
1676 return true;
1677 }
1678
1679 if (const CheckFn *Callback = AllocatingMemFnMap.lookup(Call)) {
1680 State = MallocBindRetVal(C, Call, State, false);
1681 (*Callback)(this, State, Call, C);
1682 return true;
1683 }
1684
1685 if (const CheckFn *Callback = ReallocatingMemFnMap.lookup(Call)) {
1686 State = MallocBindRetVal(C, Call, State, false);
1687 (*Callback)(this, State, Call, C);
1688 return true;
1689 }
1690
1691 if (isStandardNew(Call)) {
1692 State = MallocBindRetVal(C, Call, State, false);
1693 checkCXXNewOrCXXDelete(State, Call, C);
1694 return true;
1695 }
1696
1697 if (isStandardDelete(Call)) {
1698 checkCXXNewOrCXXDelete(State, Call, C);
1699 return true;
1700 }
1701
1702 if (const CheckFn *Callback = AllocaMemFnMap.lookup(Call)) {
1703 State = MallocBindRetVal(C, Call, State, true);
1704 (*Callback)(this, State, Call, C);
1705 return true;
1706 }
1707
1708 if (isFreeingOwnershipAttrCall(Call)) {
1709 checkOwnershipAttr(State, Call, C);
1710 return true;
1711 }
1712
1713 if (isAllocatingOwnershipAttrCall(Call)) {
1714 State = MallocBindRetVal(C, Call, State, false);
1715 checkOwnershipAttr(State, Call, C);
1716 return true;
1717 }
1718
1719 return false;
1720}
1721
1722// Performs a 0-sized allocations check.
1723ProgramStateRef MallocChecker::ProcessZeroAllocCheck(
1724 CheckerContext &C, const CallEvent &Call, const unsigned IndexOfSizeArg,
1725 ProgramStateRef State, std::optional<SVal> RetVal) {
1726 if (!State)
1727 return nullptr;
1728
1729 const Expr *Arg = nullptr;
1730
1731 if (const CallExpr *CE = dyn_cast<CallExpr>(Call.getOriginExpr())) {
1732 Arg = CE->getArg(IndexOfSizeArg);
1733 } else if (const CXXNewExpr *NE =
1734 dyn_cast<CXXNewExpr>(Call.getOriginExpr())) {
1735 if (NE->isArray()) {
1736 Arg = *NE->getArraySize();
1737 } else {
1738 return State;
1739 }
1740 } else {
1741 assert(false && "not a CallExpr or CXXNewExpr");
1742 return nullptr;
1743 }
1744
1745 if (!RetVal)
1746 RetVal = State->getSVal(Call.getOriginExpr(), C.getLocationContext());
1747
1748 assert(Arg);
1749
1750 auto DefArgVal =
1751 State->getSVal(Arg, Call.getLocationContext()).getAs<DefinedSVal>();
1752
1753 if (!DefArgVal)
1754 return State;
1755
1756 // Check if the allocation size is 0.
1757 ProgramStateRef TrueState, FalseState;
1758 SValBuilder &SvalBuilder = State->getStateManager().getSValBuilder();
1759 DefinedSVal Zero =
1760 SvalBuilder.makeZeroVal(Arg->getType()).castAs<DefinedSVal>();
1761
1762 std::tie(TrueState, FalseState) =
1763 State->assume(SvalBuilder.evalEQ(State, *DefArgVal, Zero));
1764
1765 if (TrueState && !FalseState) {
1766 SymbolRef Sym = RetVal->getAsLocSymbol();
1767 if (!Sym)
1768 return State;
1769
1770 const RefState *RS = State->get<RegionState>(Sym);
1771 if (RS) {
1772 if (RS->isAllocated())
1773 return TrueState->set<RegionState>(
1774 Sym, RefState::getAllocatedOfSizeZero(RS));
1775 return State;
1776 }
1777 // Case of zero-size realloc. Historically 'realloc(ptr, 0)' is treated as
1778 // 'free(ptr)' and the returned value from 'realloc(ptr, 0)' is not
1779 // tracked. Add zero-reallocated Sym to the state to catch references
1780 // to zero-allocated memory.
1781 return TrueState->add<ReallocSizeZeroSymbols>(Sym);
1782 }
1783
1784 // Assume the value is non-zero going forward.
1785 assert(FalseState);
1786 return FalseState;
1787}
1788
1790 QualType Result = T, PointeeType = T->getPointeeType();
1791 while (!PointeeType.isNull()) {
1792 Result = PointeeType;
1793 PointeeType = PointeeType->getPointeeType();
1794 }
1795 return Result;
1796}
1797
1798/// \returns true if the constructor invoked by \p NE has an argument of a
1799/// pointer/reference to a record type.
1801
1802 const CXXConstructExpr *ConstructE = NE->getConstructExpr();
1803 if (!ConstructE)
1804 return false;
1805
1806 if (!NE->getAllocatedType()->getAsCXXRecordDecl())
1807 return false;
1808
1809 const CXXConstructorDecl *CtorD = ConstructE->getConstructor();
1810
1811 // Iterate over the constructor parameters.
1812 for (const auto *CtorParam : CtorD->parameters()) {
1813
1814 QualType CtorParamPointeeT = CtorParam->getType()->getPointeeType();
1815 if (CtorParamPointeeT.isNull())
1816 continue;
1817
1818 CtorParamPointeeT = getDeepPointeeType(CtorParamPointeeT);
1819
1820 if (CtorParamPointeeT->getAsCXXRecordDecl())
1821 return true;
1822 }
1823
1824 return false;
1825}
1826
1828MallocChecker::processNewAllocation(const CXXAllocatorCall &Call,
1829 CheckerContext &C,
1830 AllocationFamily Family) const {
1832 return nullptr;
1833
1834 const CXXNewExpr *NE = Call.getOriginExpr();
1835 const ParentMap &PM = C.getLocationContext()->getParentMap();
1836 ProgramStateRef State = C.getState();
1837
1838 // Non-trivial constructors have a chance to escape 'this', but marking all
1839 // invocations of trivial constructors as escaped would cause too great of
1840 // reduction of true positives, so let's just do that for constructors that
1841 // have an argument of a pointer-to-record type.
1843 return State;
1844
1845 // The return value from operator new is bound to a specified initialization
1846 // value (if any) and we don't want to loose this value. So we call
1847 // MallocUpdateRefState() instead of MallocMemAux() which breaks the
1848 // existing binding.
1849 SVal Target = Call.getObjectUnderConstruction();
1850 if (Call.getOriginExpr()->isArray()) {
1851 if (auto SizeEx = NE->getArraySize())
1852 checkTaintedness(C, Call, C.getSVal(*SizeEx), State,
1853 AllocationFamily(AF_CXXNewArray));
1854 }
1855
1856 State = MallocUpdateRefState(C, NE, State, Family, Target);
1857 State = ProcessZeroAllocCheck(C, Call, 0, State, Target);
1858 return State;
1859}
1860
1861void MallocChecker::checkNewAllocator(const CXXAllocatorCall &Call,
1862 CheckerContext &C) const {
1863 if (!C.wasInlined) {
1864 ProgramStateRef State = processNewAllocation(
1865 Call, C,
1866 AllocationFamily(Call.getOriginExpr()->isArray() ? AF_CXXNewArray
1867 : AF_CXXNew));
1868 C.addTransition(State);
1869 }
1870}
1871
1873 // If the first selector piece is one of the names below, assume that the
1874 // object takes ownership of the memory, promising to eventually deallocate it
1875 // with free().
1876 // Ex: [NSData dataWithBytesNoCopy:bytes length:10];
1877 // (...unless a 'freeWhenDone' parameter is false, but that's checked later.)
1878 StringRef FirstSlot = Call.getSelector().getNameForSlot(0);
1879 return FirstSlot == "dataWithBytesNoCopy" ||
1880 FirstSlot == "initWithBytesNoCopy" ||
1881 FirstSlot == "initWithCharactersNoCopy";
1882}
1883
1884static std::optional<bool> getFreeWhenDoneArg(const ObjCMethodCall &Call) {
1885 Selector S = Call.getSelector();
1886
1887 // FIXME: We should not rely on fully-constrained symbols being folded.
1888 for (unsigned i = 1; i < S.getNumArgs(); ++i)
1889 if (S.getNameForSlot(i) == "freeWhenDone")
1890 return !Call.getArgSVal(i).isZeroConstant();
1891
1892 return std::nullopt;
1893}
1894
1895void MallocChecker::checkPostObjCMessage(const ObjCMethodCall &Call,
1896 CheckerContext &C) const {
1897 if (C.wasInlined)
1898 return;
1899
1901 return;
1902
1903 if (std::optional<bool> FreeWhenDone = getFreeWhenDoneArg(Call))
1904 if (!*FreeWhenDone)
1905 return;
1906
1907 if (Call.hasNonZeroCallbackArg())
1908 return;
1909
1910 bool IsKnownToBeAllocatedMemory;
1911 ProgramStateRef State = FreeMemAux(C, Call.getArgExpr(0), Call, C.getState(),
1912 /*Hold=*/true, IsKnownToBeAllocatedMemory,
1913 AllocationFamily(AF_Malloc),
1914 /*ReturnsNullOnFailure=*/true);
1915
1916 C.addTransition(State);
1917}
1918
1920MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallEvent &Call,
1921 const OwnershipAttr *Att,
1922 ProgramStateRef State) const {
1923 if (!State)
1924 return nullptr;
1925
1926 auto attrClassName = Att->getModule()->getName();
1927 auto Family = AllocationFamily(AF_Custom, attrClassName);
1928
1929 if (!Att->args().empty()) {
1930 return MallocMemAux(C, Call,
1931 Call.getArgExpr(Att->args_begin()->getASTIndex()),
1932 UnknownVal(), State, Family);
1933 }
1934 return MallocMemAux(C, Call, UnknownVal(), UnknownVal(), State, Family);
1935}
1936
1937ProgramStateRef MallocChecker::MallocBindRetVal(CheckerContext &C,
1938 const CallEvent &Call,
1939 ProgramStateRef State,
1940 bool isAlloca) const {
1941 const Expr *CE = Call.getOriginExpr();
1942
1943 // We expect the allocation functions to return a pointer.
1944 if (!Loc::isLocType(CE->getType()))
1945 return nullptr;
1946
1947 unsigned Count = C.blockCount();
1948 SValBuilder &SVB = C.getSValBuilder();
1949 const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
1950 DefinedSVal RetVal =
1951 isAlloca ? SVB.getAllocaRegionVal(CE, LCtx, Count)
1952 : SVB.getConjuredHeapSymbolVal(Call.getCFGElementRef(), LCtx,
1953 CE->getType(), Count);
1954 return State->BindExpr(CE, C.getLocationContext(), RetVal);
1955}
1956
1957ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
1958 const CallEvent &Call,
1959 const Expr *SizeEx, SVal Init,
1960 ProgramStateRef State,
1961 AllocationFamily Family) const {
1962 if (!State)
1963 return nullptr;
1964
1965 assert(SizeEx);
1966 return MallocMemAux(C, Call, C.getSVal(SizeEx), Init, State, Family);
1967}
1968
1969void MallocChecker::reportTaintBug(StringRef Msg, ProgramStateRef State,
1970 CheckerContext &C,
1971 llvm::ArrayRef<SymbolRef> TaintedSyms,
1972 AllocationFamily Family) const {
1973 if (ExplodedNode *N = C.generateNonFatalErrorNode(State, this)) {
1974 auto R =
1975 std::make_unique<PathSensitiveBugReport>(TaintedAllocChecker, Msg, N);
1976 for (const auto *TaintedSym : TaintedSyms) {
1977 R->markInteresting(TaintedSym);
1978 }
1979 C.emitReport(std::move(R));
1980 }
1981}
1982
1983void MallocChecker::checkTaintedness(CheckerContext &C, const CallEvent &Call,
1984 const SVal SizeSVal, ProgramStateRef State,
1985 AllocationFamily Family) const {
1986 if (!TaintedAllocChecker.isEnabled())
1987 return;
1988 std::vector<SymbolRef> TaintedSyms =
1989 taint::getTaintedSymbols(State, SizeSVal);
1990 if (TaintedSyms.empty())
1991 return;
1992
1993 SValBuilder &SVB = C.getSValBuilder();
1994 QualType SizeTy = SVB.getContext().getSizeType();
1995 QualType CmpTy = SVB.getConditionType();
1996 // In case the symbol is tainted, we give a warning if the
1997 // size is larger than SIZE_MAX/4
1998 BasicValueFactory &BVF = SVB.getBasicValueFactory();
1999 const llvm::APSInt MaxValInt = BVF.getMaxValue(SizeTy);
2000 NonLoc MaxLength =
2001 SVB.makeIntVal(MaxValInt / APSIntType(MaxValInt).getValue(4));
2002 std::optional<NonLoc> SizeNL = SizeSVal.getAs<NonLoc>();
2003 auto Cmp = SVB.evalBinOpNN(State, BO_GE, *SizeNL, MaxLength, CmpTy)
2004 .getAs<DefinedOrUnknownSVal>();
2005 if (!Cmp)
2006 return;
2007 auto [StateTooLarge, StateNotTooLarge] = State->assume(*Cmp);
2008 if (!StateTooLarge && StateNotTooLarge) {
2009 // We can prove that size is not too large so there is no issue.
2010 return;
2011 }
2012
2013 std::string Callee = "Memory allocation function";
2014 if (Call.getCalleeIdentifier())
2015 Callee = Call.getCalleeIdentifier()->getName().str();
2016 reportTaintBug(
2017 Callee + " is called with a tainted (potentially attacker controlled) "
2018 "value. Make sure the value is bound checked.",
2019 State, C, TaintedSyms, Family);
2020}
2021
2022ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
2023 const CallEvent &Call, SVal Size,
2024 SVal Init, ProgramStateRef State,
2025 AllocationFamily Family) const {
2026 if (!State)
2027 return nullptr;
2028
2029 const Expr *CE = Call.getOriginExpr();
2030
2031 // We expect the malloc functions to return a pointer.
2032 // Should have been already checked.
2033 assert(Loc::isLocType(CE->getType()) &&
2034 "Allocation functions must return a pointer");
2035
2036 const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
2037 SVal RetVal = State->getSVal(CE, C.getLocationContext());
2038
2039 // Fill the region with the initialization value.
2040 State = State->bindDefaultInitial(RetVal, Init, LCtx);
2041
2042 // If Size is somehow undefined at this point, this line prevents a crash.
2043 if (Size.isUndef())
2044 Size = UnknownVal();
2045
2046 checkTaintedness(C, Call, Size, State, AllocationFamily(AF_Malloc));
2047
2048 // Set the region's extent.
2049 State = setDynamicExtent(State, RetVal.getAsRegion(),
2050 Size.castAs<DefinedOrUnknownSVal>());
2051
2052 return MallocUpdateRefState(C, CE, State, Family);
2053}
2054
2056 ProgramStateRef State,
2057 AllocationFamily Family,
2058 std::optional<SVal> RetVal) {
2059 if (!State)
2060 return nullptr;
2061
2062 // Get the return value.
2063 if (!RetVal)
2064 RetVal = State->getSVal(E, C.getLocationContext());
2065
2066 // We expect the malloc functions to return a pointer.
2067 if (!RetVal->getAs<Loc>())
2068 return nullptr;
2069
2070 SymbolRef Sym = RetVal->getAsLocSymbol();
2071
2072 // NOTE: If this was an `alloca()` call, then `RetVal` holds an
2073 // `AllocaRegion`, so `Sym` will be a nullpointer because `AllocaRegion`s do
2074 // not have an associated symbol. However, this distinct region type means
2075 // that we don't need to store anything about them in `RegionState`.
2076
2077 if (Sym)
2078 return State->set<RegionState>(Sym, RefState::getAllocated(Family, E));
2079
2080 return State;
2081}
2082
2083ProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
2084 const CallEvent &Call,
2085 const OwnershipAttr *Att,
2086 ProgramStateRef State) const {
2087 if (!State)
2088 return nullptr;
2089
2090 auto attrClassName = Att->getModule()->getName();
2091 auto Family = AllocationFamily(AF_Custom, attrClassName);
2092
2093 bool IsKnownToBeAllocated = false;
2094
2095 for (const auto &Arg : Att->args()) {
2096 ProgramStateRef StateI =
2097 FreeMemAux(C, Call, State, Arg.getASTIndex(),
2098 Att->getOwnKind() == OwnershipAttr::Holds,
2099 IsKnownToBeAllocated, Family);
2100 if (StateI)
2101 State = StateI;
2102 }
2103 return State;
2104}
2105
2106ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
2107 const CallEvent &Call,
2108 ProgramStateRef State, unsigned Num,
2109 bool Hold, bool &IsKnownToBeAllocated,
2110 AllocationFamily Family,
2111 bool ReturnsNullOnFailure) const {
2112 if (!State)
2113 return nullptr;
2114
2115 if (Call.getNumArgs() < (Num + 1))
2116 return nullptr;
2117
2118 return FreeMemAux(C, Call.getArgExpr(Num), Call, State, Hold,
2119 IsKnownToBeAllocated, Family, ReturnsNullOnFailure);
2120}
2121
2122/// Checks if the previous call to free on the given symbol failed - if free
2123/// failed, returns true. Also, returns the corresponding return value symbol.
2125 SymbolRef Sym, SymbolRef &RetStatusSymbol) {
2126 const SymbolRef *Ret = State->get<FreeReturnValue>(Sym);
2127 if (Ret) {
2128 assert(*Ret && "We should not store the null return symbol");
2129 ConstraintManager &CMgr = State->getConstraintManager();
2130 ConditionTruthVal FreeFailed = CMgr.isNull(State, *Ret);
2131 RetStatusSymbol = *Ret;
2132 return FreeFailed.isConstrainedTrue();
2133 }
2134 return false;
2135}
2136
2137static void printOwnershipTakesList(raw_ostream &os, CheckerContext &C,
2138 const Expr *E) {
2139 const CallExpr *CE = dyn_cast<CallExpr>(E);
2140
2141 if (!CE)
2142 return;
2143
2144 const FunctionDecl *FD = CE->getDirectCallee();
2145 if (!FD)
2146 return;
2147
2148 // Only one ownership_takes attribute is allowed.
2149 for (const auto *I : FD->specific_attrs<OwnershipAttr>()) {
2150 if (I->getOwnKind() != OwnershipAttr::Takes)
2151 continue;
2152
2153 os << ", which takes ownership of '" << I->getModule()->getName() << '\'';
2154 break;
2155 }
2156}
2157
2158static bool printMemFnName(raw_ostream &os, CheckerContext &C, const Expr *E) {
2159 if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
2160 // FIXME: This doesn't handle indirect calls.
2161 const FunctionDecl *FD = CE->getDirectCallee();
2162 if (!FD)
2163 return false;
2164
2165 os << '\'' << *FD;
2166
2167 if (!FD->isOverloadedOperator())
2168 os << "()";
2169
2170 os << '\'';
2171 return true;
2172 }
2173
2174 if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) {
2175 if (Msg->isInstanceMessage())
2176 os << "-";
2177 else
2178 os << "+";
2179 Msg->getSelector().print(os);
2180 return true;
2181 }
2182
2183 if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
2184 os << "'"
2185 << getOperatorSpelling(NE->getOperatorNew()->getOverloadedOperator())
2186 << "'";
2187 return true;
2188 }
2189
2190 if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(E)) {
2191 os << "'"
2192 << getOperatorSpelling(DE->getOperatorDelete()->getOverloadedOperator())
2193 << "'";
2194 return true;
2195 }
2196
2197 return false;
2198}
2199
2200static void printExpectedAllocName(raw_ostream &os, AllocationFamily Family) {
2201
2202 switch (Family.Kind) {
2203 case AF_Malloc:
2204 os << "'malloc()'";
2205 return;
2206 case AF_CXXNew:
2207 os << "'new'";
2208 return;
2209 case AF_CXXNewArray:
2210 os << "'new[]'";
2211 return;
2212 case AF_IfNameIndex:
2213 os << "'if_nameindex()'";
2214 return;
2215 case AF_InnerBuffer:
2216 os << "container-specific allocator";
2217 return;
2218 case AF_Custom:
2219 os << Family.CustomName.value();
2220 return;
2221 case AF_Alloca:
2222 case AF_None:
2223 assert(false && "not a deallocation expression");
2224 }
2225}
2226
2227static void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family) {
2228 switch (Family.Kind) {
2229 case AF_Malloc:
2230 os << "'free()'";
2231 return;
2232 case AF_CXXNew:
2233 os << "'delete'";
2234 return;
2235 case AF_CXXNewArray:
2236 os << "'delete[]'";
2237 return;
2238 case AF_IfNameIndex:
2239 os << "'if_freenameindex()'";
2240 return;
2241 case AF_InnerBuffer:
2242 os << "container-specific deallocator";
2243 return;
2244 case AF_Custom:
2245 os << "function that takes ownership of '" << Family.CustomName.value()
2246 << "\'";
2247 return;
2248 case AF_Alloca:
2249 case AF_None:
2250 assert(false && "not a deallocation expression");
2251 }
2252}
2253
2255MallocChecker::FreeMemAux(CheckerContext &C, const Expr *ArgExpr,
2256 const CallEvent &Call, ProgramStateRef State,
2257 bool Hold, bool &IsKnownToBeAllocated,
2258 AllocationFamily Family, bool ReturnsNullOnFailure,
2259 std::optional<SVal> ArgValOpt) const {
2260
2261 if (!State)
2262 return nullptr;
2263
2264 SVal ArgVal = ArgValOpt.value_or(C.getSVal(ArgExpr));
2265 if (!isa<DefinedOrUnknownSVal>(ArgVal))
2266 return nullptr;
2267 DefinedOrUnknownSVal location = ArgVal.castAs<DefinedOrUnknownSVal>();
2268
2269 // Check for null dereferences.
2270 if (!isa<Loc>(location))
2271 return nullptr;
2272
2273 // The explicit NULL case, no operation is performed.
2274 ProgramStateRef notNullState, nullState;
2275 std::tie(notNullState, nullState) = State->assume(location);
2276 if (nullState && !notNullState)
2277 return nullptr;
2278
2279 // Unknown values could easily be okay
2280 // Undefined values are handled elsewhere
2281 if (ArgVal.isUnknownOrUndef())
2282 return nullptr;
2283
2284 const MemRegion *R = ArgVal.getAsRegion();
2285 const Expr *ParentExpr = Call.getOriginExpr();
2286
2287 // NOTE: We detected a bug, but the checker under whose name we would emit the
2288 // error could be disabled. Generally speaking, the MallocChecker family is an
2289 // integral part of the Static Analyzer, and disabling any part of it should
2290 // only be done under exceptional circumstances, such as frequent false
2291 // positives. If this is the case, we can reasonably believe that there are
2292 // serious faults in our understanding of the source code, and even if we
2293 // don't emit an warning, we should terminate further analysis with a sink
2294 // node.
2295
2296 // Nonlocs can't be freed, of course.
2297 // Non-region locations (labels and fixed addresses) also shouldn't be freed.
2298 if (!R) {
2299 // Exception:
2300 // If the macro ZERO_SIZE_PTR is defined, this could be a kernel source
2301 // code. In that case, the ZERO_SIZE_PTR defines a special value used for a
2302 // zero-sized memory block which is allowed to be freed, despite not being a
2303 // null pointer.
2304 if (Family.Kind != AF_Malloc || !isArgZERO_SIZE_PTR(State, C, ArgVal))
2305 HandleNonHeapDealloc(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
2306 Family);
2307 return nullptr;
2308 }
2309
2310 R = R->StripCasts();
2311
2312 // Blocks might show up as heap data, but should not be free()d
2313 if (isa<BlockDataRegion>(R)) {
2314 HandleNonHeapDealloc(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
2315 Family);
2316 return nullptr;
2317 }
2318
2319 // Parameters, locals, statics, globals, and memory returned by
2320 // __builtin_alloca() shouldn't be freed.
2321 if (!R->hasMemorySpace<UnknownSpaceRegion, HeapSpaceRegion>(State)) {
2322 // Regions returned by malloc() are represented by SymbolicRegion objects
2323 // within HeapSpaceRegion. Of course, free() can work on memory allocated
2324 // outside the current function, so UnknownSpaceRegion is also a
2325 // possibility here.
2326
2327 if (isa<AllocaRegion>(R))
2328 HandleFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
2329 else
2330 HandleNonHeapDealloc(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
2331 Family);
2332
2333 return nullptr;
2334 }
2335
2336 const SymbolicRegion *SrBase = dyn_cast<SymbolicRegion>(R->getBaseRegion());
2337 // Various cases could lead to non-symbol values here.
2338 // For now, ignore them.
2339 if (!SrBase)
2340 return nullptr;
2341
2342 SymbolRef SymBase = SrBase->getSymbol();
2343 const RefState *RsBase = State->get<RegionState>(SymBase);
2344 SymbolRef PreviousRetStatusSymbol = nullptr;
2345
2346 IsKnownToBeAllocated =
2347 RsBase && (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero());
2348
2349 if (RsBase) {
2350
2351 // Memory returned by alloca() shouldn't be freed.
2352 if (RsBase->getAllocationFamily().Kind == AF_Alloca) {
2353 HandleFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
2354 return nullptr;
2355 }
2356
2357 // Check for double free first.
2358 if ((RsBase->isReleased() || RsBase->isRelinquished()) &&
2359 !didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {
2360 HandleDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),
2361 SymBase, PreviousRetStatusSymbol);
2362 return nullptr;
2363 }
2364
2365 // If the pointer is allocated or escaped, but we are now trying to free it,
2366 // check that the call to free is proper.
2367 if (RsBase->isAllocated() || RsBase->isAllocatedOfSizeZero() ||
2368 RsBase->isEscaped()) {
2369
2370 // Check if an expected deallocation function matches the real one.
2371 bool DeallocMatchesAlloc = RsBase->getAllocationFamily() == Family;
2372 if (!DeallocMatchesAlloc) {
2373 HandleMismatchedDealloc(C, ArgExpr->getSourceRange(), ParentExpr,
2374 RsBase, SymBase, Hold);
2375 return nullptr;
2376 }
2377
2378 // Check if the memory location being freed is the actual location
2379 // allocated, or an offset.
2380 RegionOffset Offset = R->getAsOffset();
2381 if (Offset.isValid() &&
2382 !Offset.hasSymbolicOffset() &&
2383 Offset.getOffset() != 0) {
2384 const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
2385 HandleOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
2386 Family, AllocExpr);
2387 return nullptr;
2388 }
2389 }
2390 }
2391
2392 if (SymBase->getType()->isFunctionPointerType()) {
2393 HandleFunctionPtrFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
2394 Family);
2395 return nullptr;
2396 }
2397
2398 // Clean out the info on previous call to free return info.
2399 State = State->remove<FreeReturnValue>(SymBase);
2400
2401 // Keep track of the return value. If it is NULL, we will know that free
2402 // failed.
2403 if (ReturnsNullOnFailure) {
2404 SVal RetVal = C.getSVal(ParentExpr);
2405 SymbolRef RetStatusSymbol = RetVal.getAsSymbol();
2406 if (RetStatusSymbol) {
2407 C.getSymbolManager().addSymbolDependency(SymBase, RetStatusSymbol);
2408 State = State->set<FreeReturnValue>(SymBase, RetStatusSymbol);
2409 }
2410 }
2411
2412 // If we don't know anything about this symbol, a free on it may be totally
2413 // valid. If this is the case, lets assume that the allocation family of the
2414 // freeing function is the same as the symbols allocation family, and go with
2415 // that.
2416 assert(!RsBase || (RsBase && RsBase->getAllocationFamily() == Family));
2417
2418 // Assume that after memory is freed, it contains unknown values. This
2419 // conforts languages standards, since reading from freed memory is considered
2420 // UB and may result in arbitrary value.
2421 State = State->invalidateRegions({location}, Call.getCFGElementRef(),
2422 C.blockCount(), C.getLocationContext(),
2423 /*CausesPointerEscape=*/false,
2424 /*InvalidatedSymbols=*/nullptr);
2425
2426 // Normal free.
2427 if (Hold)
2428 return State->set<RegionState>(SymBase,
2429 RefState::getRelinquished(Family,
2430 ParentExpr));
2431
2432 return State->set<RegionState>(SymBase,
2433 RefState::getReleased(Family, ParentExpr));
2434}
2435
2436template <class T>
2437const T *MallocChecker::getRelevantFrontendAs(AllocationFamily Family) const {
2438 switch (Family.Kind) {
2439 case AF_Malloc:
2440 case AF_Alloca:
2441 case AF_Custom:
2442 case AF_IfNameIndex:
2443 return MallocChecker.getAs<T>();
2444 case AF_CXXNew:
2445 case AF_CXXNewArray: {
2446 const T *ND = NewDeleteChecker.getAs<T>();
2447 const T *NDL = NewDeleteLeaksChecker.getAs<T>();
2448 // Bugs corresponding to C++ new/delete allocations are split between these
2449 // two frontends.
2450 if constexpr (std::is_same_v<T, CheckerFrontend>) {
2451 assert(ND && NDL && "Casting to CheckerFrontend always succeeds");
2452 // Prefer NewDelete unless it's disabled and NewDeleteLeaks is enabled.
2453 return (!ND->isEnabled() && NDL->isEnabled()) ? NDL : ND;
2454 }
2455 assert(!(ND && NDL) &&
2456 "NewDelete and NewDeleteLeaks must not share a bug type");
2457 return ND ? ND : NDL;
2458 }
2459 case AF_InnerBuffer:
2460 return InnerPointerChecker.getAs<T>();
2461 case AF_None:
2462 assert(false && "no family");
2463 return nullptr;
2464 }
2465 assert(false && "unhandled family");
2466 return nullptr;
2467}
2468template <class T>
2469const T *MallocChecker::getRelevantFrontendAs(CheckerContext &C,
2470 SymbolRef Sym) const {
2471 if (C.getState()->contains<ReallocSizeZeroSymbols>(Sym))
2472 return MallocChecker.getAs<T>();
2473
2474 const RefState *RS = C.getState()->get<RegionState>(Sym);
2475 assert(RS);
2476 return getRelevantFrontendAs<T>(RS->getAllocationFamily());
2477}
2478
2479bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
2480 if (std::optional<nonloc::ConcreteInt> IntVal =
2481 V.getAs<nonloc::ConcreteInt>())
2482 os << "an integer (" << IntVal->getValue() << ")";
2483 else if (std::optional<loc::ConcreteInt> ConstAddr =
2484 V.getAs<loc::ConcreteInt>())
2485 os << "a constant address (" << ConstAddr->getValue() << ")";
2486 else if (std::optional<loc::GotoLabel> Label = V.getAs<loc::GotoLabel>())
2487 os << "the address of the label '" << Label->getLabel()->getName() << "'";
2488 else
2489 return false;
2490
2491 return true;
2492}
2493
2494bool MallocChecker::SummarizeRegion(ProgramStateRef State, raw_ostream &os,
2495 const MemRegion *MR) {
2496 switch (MR->getKind()) {
2497 case MemRegion::FunctionCodeRegionKind: {
2498 const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl();
2499 if (FD)
2500 os << "the address of the function '" << *FD << '\'';
2501 else
2502 os << "the address of a function";
2503 return true;
2504 }
2505 case MemRegion::BlockCodeRegionKind:
2506 os << "block text";
2507 return true;
2508 case MemRegion::BlockDataRegionKind:
2509 // FIXME: where the block came from?
2510 os << "a block";
2511 return true;
2512 default: {
2513 const MemSpaceRegion *MS = MR->getMemorySpace(State);
2514
2516 const VarRegion *VR = dyn_cast<VarRegion>(MR);
2517 const VarDecl *VD;
2518 if (VR)
2519 VD = VR->getDecl();
2520 else
2521 VD = nullptr;
2522
2523 if (VD)
2524 os << "the address of the local variable '" << VD->getName() << "'";
2525 else
2526 os << "the address of a local stack variable";
2527 return true;
2528 }
2529
2531 const VarRegion *VR = dyn_cast<VarRegion>(MR);
2532 const VarDecl *VD;
2533 if (VR)
2534 VD = VR->getDecl();
2535 else
2536 VD = nullptr;
2537
2538 if (VD)
2539 os << "the address of the parameter '" << VD->getName() << "'";
2540 else
2541 os << "the address of a parameter";
2542 return true;
2543 }
2544
2545 if (isa<GlobalsSpaceRegion>(MS)) {
2546 const VarRegion *VR = dyn_cast<VarRegion>(MR);
2547 const VarDecl *VD;
2548 if (VR)
2549 VD = VR->getDecl();
2550 else
2551 VD = nullptr;
2552
2553 if (VD) {
2554 if (VD->isStaticLocal())
2555 os << "the address of the static variable '" << VD->getName() << "'";
2556 else
2557 os << "the address of the global variable '" << VD->getName() << "'";
2558 } else
2559 os << "the address of a global variable";
2560 return true;
2561 }
2562
2563 return false;
2564 }
2565 }
2566}
2567
2568void MallocChecker::HandleNonHeapDealloc(CheckerContext &C, SVal ArgVal,
2569 SourceRange Range,
2570 const Expr *DeallocExpr,
2571 AllocationFamily Family) const {
2572 const BadFree *Frontend = getRelevantFrontendAs<BadFree>(Family);
2573 if (!Frontend)
2574 return;
2575 if (!Frontend->isEnabled()) {
2576 C.addSink();
2577 return;
2578 }
2579
2580 if (ExplodedNode *N = C.generateErrorNode()) {
2581 SmallString<100> buf;
2582 llvm::raw_svector_ostream os(buf);
2583
2584 const MemRegion *MR = ArgVal.getAsRegion();
2585 while (const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
2586 MR = ER->getSuperRegion();
2587
2588 os << "Argument to ";
2589 if (!printMemFnName(os, C, DeallocExpr))
2590 os << "deallocator";
2591
2592 os << " is ";
2593 bool Summarized =
2594 MR ? SummarizeRegion(C.getState(), os, MR) : SummarizeValue(os, ArgVal);
2595 if (Summarized)
2596 os << ", which is not memory allocated by ";
2597 else
2598 os << "not memory allocated by ";
2599
2600 printExpectedAllocName(os, Family);
2601
2602 auto R = std::make_unique<PathSensitiveBugReport>(Frontend->BadFreeBug,
2603 os.str(), N);
2604 R->markInteresting(MR);
2605 R->addRange(Range);
2606 C.emitReport(std::move(R));
2607 }
2608}
2609
2610void MallocChecker::HandleFreeAlloca(CheckerContext &C, SVal ArgVal,
2611 SourceRange Range) const {
2612 const FreeAlloca *Frontend;
2613
2614 if (MallocChecker.isEnabled())
2615 Frontend = &MallocChecker;
2616 else if (MismatchedDeallocatorChecker.isEnabled())
2617 Frontend = &MismatchedDeallocatorChecker;
2618 else {
2619 C.addSink();
2620 return;
2621 }
2622
2623 if (ExplodedNode *N = C.generateErrorNode()) {
2624 auto R = std::make_unique<PathSensitiveBugReport>(
2625 Frontend->FreeAllocaBug,
2626 "Memory allocated by 'alloca()' should not be deallocated", N);
2627 R->markInteresting(ArgVal.getAsRegion());
2628 R->addRange(Range);
2629 C.emitReport(std::move(R));
2630 }
2631}
2632
2633void MallocChecker::HandleMismatchedDealloc(CheckerContext &C,
2634 SourceRange Range,
2635 const Expr *DeallocExpr,
2636 const RefState *RS, SymbolRef Sym,
2637 bool OwnershipTransferred) const {
2638 if (!MismatchedDeallocatorChecker.isEnabled()) {
2639 C.addSink();
2640 return;
2641 }
2642
2643 if (ExplodedNode *N = C.generateErrorNode()) {
2644 SmallString<100> buf;
2645 llvm::raw_svector_ostream os(buf);
2646
2647 const Expr *AllocExpr = cast<Expr>(RS->getStmt());
2648 SmallString<20> AllocBuf;
2649 llvm::raw_svector_ostream AllocOs(AllocBuf);
2650 SmallString<20> DeallocBuf;
2651 llvm::raw_svector_ostream DeallocOs(DeallocBuf);
2652
2653 if (OwnershipTransferred) {
2654 if (printMemFnName(DeallocOs, C, DeallocExpr))
2655 os << DeallocOs.str() << " cannot";
2656 else
2657 os << "Cannot";
2658
2659 os << " take ownership of memory";
2660
2661 if (printMemFnName(AllocOs, C, AllocExpr))
2662 os << " allocated by " << AllocOs.str();
2663 } else {
2664 os << "Memory";
2665 if (printMemFnName(AllocOs, C, AllocExpr))
2666 os << " allocated by " << AllocOs.str();
2667
2668 os << " should be deallocated by ";
2669 printExpectedDeallocName(os, RS->getAllocationFamily());
2670
2671 if (printMemFnName(DeallocOs, C, DeallocExpr))
2672 os << ", not " << DeallocOs.str();
2673
2674 printOwnershipTakesList(os, C, DeallocExpr);
2675 }
2676
2677 auto R = std::make_unique<PathSensitiveBugReport>(
2678 MismatchedDeallocatorChecker.MismatchedDeallocBug, os.str(), N);
2679 R->markInteresting(Sym);
2680 R->addRange(Range);
2681 R->addVisitor<MallocBugVisitor>(Sym);
2682 C.emitReport(std::move(R));
2683 }
2684}
2685
2686void MallocChecker::HandleOffsetFree(CheckerContext &C, SVal ArgVal,
2687 SourceRange Range, const Expr *DeallocExpr,
2688 AllocationFamily Family,
2689 const Expr *AllocExpr) const {
2690 const OffsetFree *Frontend = getRelevantFrontendAs<OffsetFree>(Family);
2691 if (!Frontend)
2692 return;
2693 if (!Frontend->isEnabled()) {
2694 C.addSink();
2695 return;
2696 }
2697
2698 ExplodedNode *N = C.generateErrorNode();
2699 if (!N)
2700 return;
2701
2702 SmallString<100> buf;
2703 llvm::raw_svector_ostream os(buf);
2704 SmallString<20> AllocNameBuf;
2705 llvm::raw_svector_ostream AllocNameOs(AllocNameBuf);
2706
2707 const MemRegion *MR = ArgVal.getAsRegion();
2708 assert(MR && "Only MemRegion based symbols can have offset free errors");
2709
2710 RegionOffset Offset = MR->getAsOffset();
2711 assert((Offset.isValid() &&
2712 !Offset.hasSymbolicOffset() &&
2713 Offset.getOffset() != 0) &&
2714 "Only symbols with a valid offset can have offset free errors");
2715
2716 int offsetBytes = Offset.getOffset() / C.getASTContext().getCharWidth();
2717
2718 os << "Argument to ";
2719 if (!printMemFnName(os, C, DeallocExpr))
2720 os << "deallocator";
2721 os << " is offset by "
2722 << offsetBytes
2723 << " "
2724 << ((abs(offsetBytes) > 1) ? "bytes" : "byte")
2725 << " from the start of ";
2726 if (AllocExpr && printMemFnName(AllocNameOs, C, AllocExpr))
2727 os << "memory allocated by " << AllocNameOs.str();
2728 else
2729 os << "allocated memory";
2730
2731 auto R = std::make_unique<PathSensitiveBugReport>(Frontend->OffsetFreeBug,
2732 os.str(), N);
2733 R->markInteresting(MR->getBaseRegion());
2734 R->addRange(Range);
2735 C.emitReport(std::move(R));
2736}
2737
2738void MallocChecker::HandleUseAfterFree(CheckerContext &C, SourceRange Range,
2739 SymbolRef Sym) const {
2740 const UseFree *Frontend = getRelevantFrontendAs<UseFree>(C, Sym);
2741 if (!Frontend)
2742 return;
2743 if (!Frontend->isEnabled()) {
2744 C.addSink();
2745 return;
2746 }
2747
2748 if (ExplodedNode *N = C.generateErrorNode()) {
2749 AllocationFamily AF =
2750 C.getState()->get<RegionState>(Sym)->getAllocationFamily();
2751
2752 auto R = std::make_unique<PathSensitiveBugReport>(
2753 Frontend->UseFreeBug,
2754 AF.Kind == AF_InnerBuffer
2755 ? "Inner pointer of container used after re/deallocation"
2756 : "Use of memory after it is released",
2757 N);
2758
2759 R->markInteresting(Sym);
2760 R->addRange(Range);
2761 R->addVisitor<MallocBugVisitor>(Sym);
2762
2763 if (AF.Kind == AF_InnerBuffer)
2765
2766 C.emitReport(std::move(R));
2767 }
2768}
2769
2770void MallocChecker::HandleDoubleFree(CheckerContext &C, SourceRange Range,
2771 bool Released, SymbolRef Sym,
2772 SymbolRef PrevSym) const {
2773 const DoubleFree *Frontend = getRelevantFrontendAs<DoubleFree>(C, Sym);
2774 if (!Frontend)
2775 return;
2776 if (!Frontend->isEnabled()) {
2777 C.addSink();
2778 return;
2779 }
2780
2781 if (ExplodedNode *N = C.generateErrorNode()) {
2782 auto R = std::make_unique<PathSensitiveBugReport>(
2783 Frontend->DoubleFreeBug,
2784 (Released ? "Attempt to release already released memory"
2785 : "Attempt to release non-owned memory"),
2786 N);
2787 if (Range.isValid())
2788 R->addRange(Range);
2789 R->markInteresting(Sym);
2790 if (PrevSym)
2791 R->markInteresting(PrevSym);
2792 R->addVisitor<MallocBugVisitor>(Sym);
2793 C.emitReport(std::move(R));
2794 }
2795}
2796
2797void MallocChecker::HandleUseZeroAlloc(CheckerContext &C, SourceRange Range,
2798 SymbolRef Sym) const {
2799 const UseZeroAllocated *Frontend =
2800 getRelevantFrontendAs<UseZeroAllocated>(C, Sym);
2801 if (!Frontend)
2802 return;
2803 if (!Frontend->isEnabled()) {
2804 C.addSink();
2805 return;
2806 }
2807
2808 if (ExplodedNode *N = C.generateErrorNode()) {
2809 auto R = std::make_unique<PathSensitiveBugReport>(
2810 Frontend->UseZeroAllocatedBug, "Use of memory allocated with size zero",
2811 N);
2812
2813 R->addRange(Range);
2814 if (Sym) {
2815 R->markInteresting(Sym);
2816 R->addVisitor<MallocBugVisitor>(Sym);
2817 }
2818 C.emitReport(std::move(R));
2819 }
2820}
2821
2822void MallocChecker::HandleFunctionPtrFree(CheckerContext &C, SVal ArgVal,
2823 SourceRange Range,
2824 const Expr *FreeExpr,
2825 AllocationFamily Family) const {
2826 const BadFree *Frontend = getRelevantFrontendAs<BadFree>(Family);
2827 if (!Frontend)
2828 return;
2829 if (!Frontend->isEnabled()) {
2830 C.addSink();
2831 return;
2832 }
2833
2834 if (ExplodedNode *N = C.generateErrorNode()) {
2835 SmallString<100> Buf;
2836 llvm::raw_svector_ostream Os(Buf);
2837
2838 const MemRegion *MR = ArgVal.getAsRegion();
2839 while (const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
2840 MR = ER->getSuperRegion();
2841
2842 Os << "Argument to ";
2843 if (!printMemFnName(Os, C, FreeExpr))
2844 Os << "deallocator";
2845
2846 Os << " is a function pointer";
2847
2848 auto R = std::make_unique<PathSensitiveBugReport>(Frontend->BadFreeBug,
2849 Os.str(), N);
2850 R->markInteresting(MR);
2851 R->addRange(Range);
2852 C.emitReport(std::move(R));
2853 }
2854}
2855
2857MallocChecker::ReallocMemAux(CheckerContext &C, const CallEvent &Call,
2858 bool ShouldFreeOnFail, ProgramStateRef State,
2859 AllocationFamily Family, bool SuffixWithN) const {
2860 if (!State)
2861 return nullptr;
2862
2863 const CallExpr *CE = cast<CallExpr>(Call.getOriginExpr());
2864
2865 if ((SuffixWithN && CE->getNumArgs() < 3) || CE->getNumArgs() < 2)
2866 return nullptr;
2867
2868 const Expr *arg0Expr = CE->getArg(0);
2869 SVal Arg0Val = C.getSVal(arg0Expr);
2870 if (!isa<DefinedOrUnknownSVal>(Arg0Val))
2871 return nullptr;
2872 DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
2873
2874 SValBuilder &svalBuilder = C.getSValBuilder();
2875
2876 DefinedOrUnknownSVal PtrEQ = svalBuilder.evalEQ(
2877 State, arg0Val, svalBuilder.makeNullWithType(arg0Expr->getType()));
2878
2879 // Get the size argument.
2880 const Expr *Arg1 = CE->getArg(1);
2881
2882 // Get the value of the size argument.
2883 SVal TotalSize = C.getSVal(Arg1);
2884 if (SuffixWithN)
2885 TotalSize = evalMulForBufferSize(C, Arg1, CE->getArg(2));
2886 if (!isa<DefinedOrUnknownSVal>(TotalSize))
2887 return nullptr;
2888
2889 // Compare the size argument to 0.
2890 DefinedOrUnknownSVal SizeZero = svalBuilder.evalEQ(
2891 State, TotalSize.castAs<DefinedOrUnknownSVal>(),
2892 svalBuilder.makeIntValWithWidth(
2893 svalBuilder.getContext().getCanonicalSizeType(), 0));
2894
2895 ProgramStateRef StatePtrIsNull, StatePtrNotNull;
2896 std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ);
2897 ProgramStateRef StateSizeIsZero, StateSizeNotZero;
2898 std::tie(StateSizeIsZero, StateSizeNotZero) = State->assume(SizeZero);
2899 // We only assume exceptional states if they are definitely true; if the
2900 // state is under-constrained, assume regular realloc behavior.
2901 bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
2902 bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
2903
2904 // If the ptr is NULL and the size is not 0, the call is equivalent to
2905 // malloc(size).
2906 if (PrtIsNull && !SizeIsZero) {
2907 ProgramStateRef stateMalloc = MallocMemAux(
2908 C, Call, TotalSize, UndefinedVal(), StatePtrIsNull, Family);
2909 return stateMalloc;
2910 }
2911
2912 // Proccess as allocation of 0 bytes.
2913 if (PrtIsNull && SizeIsZero)
2914 return State;
2915
2916 assert(!PrtIsNull);
2917
2918 bool IsKnownToBeAllocated = false;
2919
2920 // If the size is 0, free the memory.
2921 if (SizeIsZero)
2922 // The semantics of the return value are:
2923 // If size was equal to 0, either NULL or a pointer suitable to be passed
2924 // to free() is returned. We just free the input pointer and do not add
2925 // any constrains on the output pointer.
2926 if (ProgramStateRef stateFree = FreeMemAux(
2927 C, Call, StateSizeIsZero, 0, false, IsKnownToBeAllocated, Family))
2928 return stateFree;
2929
2930 // Default behavior.
2931 if (ProgramStateRef stateFree =
2932 FreeMemAux(C, Call, State, 0, false, IsKnownToBeAllocated, Family)) {
2933
2934 ProgramStateRef stateRealloc =
2935 MallocMemAux(C, Call, TotalSize, UnknownVal(), stateFree, Family);
2936 if (!stateRealloc)
2937 return nullptr;
2938
2939 OwnershipAfterReallocKind Kind = OAR_ToBeFreedAfterFailure;
2940 if (ShouldFreeOnFail)
2941 Kind = OAR_FreeOnFailure;
2942 else if (!IsKnownToBeAllocated)
2943 Kind = OAR_DoNotTrackAfterFailure;
2944
2945 // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
2946 SymbolRef FromPtr = arg0Val.getLocSymbolInBase();
2947 SVal RetVal = stateRealloc->getSVal(CE, C.getLocationContext());
2948 SymbolRef ToPtr = RetVal.getAsSymbol();
2949 assert(FromPtr && ToPtr &&
2950 "By this point, FreeMemAux and MallocMemAux should have checked "
2951 "whether the argument or the return value is symbolic!");
2952
2953 // Record the info about the reallocated symbol so that we could properly
2954 // process failed reallocation.
2955 stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
2956 ReallocPair(FromPtr, Kind));
2957 // The reallocated symbol should stay alive for as long as the new symbol.
2958 C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
2959 return stateRealloc;
2960 }
2961 return nullptr;
2962}
2963
2964ProgramStateRef MallocChecker::CallocMem(CheckerContext &C,
2965 const CallEvent &Call,
2966 ProgramStateRef State) const {
2967 if (!State)
2968 return nullptr;
2969
2970 if (Call.getNumArgs() < 2)
2971 return nullptr;
2972
2973 SValBuilder &svalBuilder = C.getSValBuilder();
2974 SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
2975 SVal TotalSize =
2976 evalMulForBufferSize(C, Call.getArgExpr(0), Call.getArgExpr(1));
2977
2978 return MallocMemAux(C, Call, TotalSize, zeroVal, State,
2979 AllocationFamily(AF_Malloc));
2980}
2981
2982MallocChecker::LeakInfo MallocChecker::getAllocationSite(const ExplodedNode *N,
2983 SymbolRef Sym,
2984 CheckerContext &C) {
2985 const LocationContext *LeakContext = N->getLocationContext();
2986 // Walk the ExplodedGraph backwards and find the first node that referred to
2987 // the tracked symbol.
2988 const ExplodedNode *AllocNode = N;
2989 const MemRegion *ReferenceRegion = nullptr;
2990
2991 while (N) {
2992 ProgramStateRef State = N->getState();
2993 if (!State->get<RegionState>(Sym))
2994 break;
2995
2996 // Find the most recent expression bound to the symbol in the current
2997 // context.
2998 if (!ReferenceRegion) {
2999 if (const MemRegion *MR = C.getLocationRegionIfPostStore(N)) {
3000 SVal Val = State->getSVal(MR);
3001 if (Val.getAsLocSymbol() == Sym) {
3002 const VarRegion *VR = MR->getBaseRegion()->getAs<VarRegion>();
3003 // Do not show local variables belonging to a function other than
3004 // where the error is reported.
3005 if (!VR || (VR->getStackFrame() == LeakContext->getStackFrame()))
3006 ReferenceRegion = MR;
3007 }
3008 }
3009 }
3010
3011 // Allocation node, is the last node in the current or parent context in
3012 // which the symbol was tracked.
3013 const LocationContext *NContext = N->getLocationContext();
3014 if (NContext == LeakContext ||
3015 NContext->isParentOf(LeakContext))
3016 AllocNode = N;
3017 N = N->pred_empty() ? nullptr : *(N->pred_begin());
3018 }
3019
3020 return LeakInfo(AllocNode, ReferenceRegion);
3021}
3022
3023void MallocChecker::HandleLeak(SymbolRef Sym, ExplodedNode *N,
3024 CheckerContext &C) const {
3025 assert(N && "HandleLeak is only called with a non-null node");
3026
3027 const RefState *RS = C.getState()->get<RegionState>(Sym);
3028 assert(RS && "cannot leak an untracked symbol");
3029 AllocationFamily Family = RS->getAllocationFamily();
3030
3031 if (Family.Kind == AF_Alloca)
3032 return;
3033
3034 const Leak *Frontend = getRelevantFrontendAs<Leak>(Family);
3035 // Note that for leaks we don't add a sink when the relevant frontend is
3036 // disabled because the leak is reported with a non-fatal error node, while
3037 // the sink would be the "silent" alternative of a (fatal) error node.
3038 if (!Frontend || !Frontend->isEnabled())
3039 return;
3040
3041 // Most bug reports are cached at the location where they occurred.
3042 // With leaks, we want to unique them by the location where they were
3043 // allocated, and only report a single path.
3044 PathDiagnosticLocation LocUsedForUniqueing;
3045 const ExplodedNode *AllocNode = nullptr;
3046 const MemRegion *Region = nullptr;
3047 std::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
3048
3049 const Stmt *AllocationStmt = AllocNode->getStmtForDiagnostics();
3050 if (AllocationStmt)
3051 LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt,
3052 C.getSourceManager(),
3053 AllocNode->getLocationContext());
3054
3055 SmallString<200> buf;
3056 llvm::raw_svector_ostream os(buf);
3057 if (Region && Region->canPrintPretty()) {
3058 os << "Potential leak of memory pointed to by ";
3059 Region->printPretty(os);
3060 } else {
3061 os << "Potential memory leak";
3062 }
3063
3064 auto R = std::make_unique<PathSensitiveBugReport>(
3065 Frontend->LeakBug, os.str(), N, LocUsedForUniqueing,
3066 AllocNode->getLocationContext()->getDecl());
3067 R->markInteresting(Sym);
3068 R->addVisitor<MallocBugVisitor>(Sym, true);
3069 if (ShouldRegisterNoOwnershipChangeVisitor)
3070 R->addVisitor<NoMemOwnershipChangeVisitor>(Sym, this);
3071 C.emitReport(std::move(R));
3072}
3073
3074void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
3075 CheckerContext &C) const
3076{
3077 ProgramStateRef state = C.getState();
3078 RegionStateTy OldRS = state->get<RegionState>();
3079 RegionStateTy::Factory &F = state->get_context<RegionState>();
3080
3081 RegionStateTy RS = OldRS;
3082 SmallVector<SymbolRef, 2> Errors;
3083 for (auto [Sym, State] : RS) {
3084 if (SymReaper.isDead(Sym)) {
3085 if (State.isAllocated() || State.isAllocatedOfSizeZero())
3086 Errors.push_back(Sym);
3087 // Remove the dead symbol from the map.
3088 RS = F.remove(RS, Sym);
3089 }
3090 }
3091
3092 if (RS == OldRS) {
3093 // We shouldn't have touched other maps yet.
3094 assert(state->get<ReallocPairs>() ==
3095 C.getState()->get<ReallocPairs>());
3096 assert(state->get<FreeReturnValue>() ==
3097 C.getState()->get<FreeReturnValue>());
3098 return;
3099 }
3100
3101 // Cleanup the Realloc Pairs Map.
3102 ReallocPairsTy RP = state->get<ReallocPairs>();
3103 for (auto [Sym, ReallocPair] : RP) {
3104 if (SymReaper.isDead(Sym) || SymReaper.isDead(ReallocPair.ReallocatedSym)) {
3105 state = state->remove<ReallocPairs>(Sym);
3106 }
3107 }
3108
3109 // Cleanup the FreeReturnValue Map.
3110 FreeReturnValueTy FR = state->get<FreeReturnValue>();
3111 for (auto [Sym, RetSym] : FR) {
3112 if (SymReaper.isDead(Sym) || SymReaper.isDead(RetSym)) {
3113 state = state->remove<FreeReturnValue>(Sym);
3114 }
3115 }
3116
3117 // Generate leak node.
3118 ExplodedNode *N = C.getPredecessor();
3119 if (!Errors.empty()) {
3120 N = C.generateNonFatalErrorNode(C.getState());
3121 if (N) {
3122 for (SymbolRef Sym : Errors) {
3123 HandleLeak(Sym, N, C);
3124 }
3125 }
3126 }
3127
3128 C.addTransition(state->set<RegionState>(RS), N);
3129}
3130
3131// Allowlist of owning smart pointers we want to recognize.
3132// Start with unique_ptr and shared_ptr; weak_ptr is excluded intentionally
3133// because it does not own the pointee.
3134static bool isSmartPtrName(StringRef Name) {
3135 return Name == "unique_ptr" || Name == "shared_ptr";
3136}
3137
3138// Check if a type is a smart owning pointer type.
3139static bool isSmartPtrType(QualType QT) {
3140 QT = QT->getCanonicalTypeUnqualified();
3141
3142 if (const auto *TST = QT->getAs<TemplateSpecializationType>()) {
3143 const TemplateDecl *TD = TST->getTemplateName().getAsTemplateDecl();
3144 if (!TD)
3145 return false;
3146
3147 const auto *ND = dyn_cast_or_null<NamedDecl>(TD->getTemplatedDecl());
3148 if (!ND)
3149 return false;
3150
3151 // For broader coverage we recognize all template classes with names that
3152 // match the allowlist even if they are not declared in namespace 'std'.
3153 return isSmartPtrName(ND->getName());
3154 }
3155
3156 return false;
3157}
3158
3159/// Helper struct for collecting smart owning pointer field regions.
3160/// This allows both hasSmartPtrField and
3161/// collectSmartPtrFieldRegions to share the same traversal logic,
3162/// ensuring consistency.
3166 llvm::SmallPtrSetImpl<const MemRegion *> *Out;
3167
3169 llvm::SmallPtrSetImpl<const MemRegion *> &Out)
3170 : Reg(Reg), C(&C), Out(&Out) {}
3171
3172 void consume(const FieldDecl *FD) {
3173 SVal L = C->getState()->getLValue(FD, loc::MemRegionVal(Reg));
3174 if (const MemRegion *FR = L.getAsRegion())
3175 Out->insert(FR);
3176 }
3177
3178 std::optional<FieldConsumer> switchToBase(const CXXRecordDecl *BaseDecl,
3179 bool IsVirtual) {
3180 // Get the base class region
3181 SVal BaseL =
3182 C->getState()->getLValue(BaseDecl, Reg->getAs<SubRegion>(), IsVirtual);
3183 if (const MemRegion *BaseObjRegion = BaseL.getAsRegion()) {
3184 // Return a consumer for the base class
3185 return FieldConsumer{BaseObjRegion, *C, *Out};
3186 }
3187 return std::nullopt;
3188 }
3189};
3190
3191/// Check if a record type has smart owning pointer fields (directly or in base
3192/// classes). When FC is provided, also collect the field regions.
3193///
3194/// This function has dual behavior:
3195/// - When FC is nullopt: Returns true if smart pointer fields are found
3196/// - When FC is provided: Always returns false, but collects field regions
3197/// as a side effect through the FieldConsumer
3198///
3199/// Note: When FC is provided, the return value should be ignored since the
3200/// function performs full traversal for collection and always returns false
3201/// to avoid early termination.
3202static bool hasSmartPtrField(const CXXRecordDecl *CRD,
3203 std::optional<FieldConsumer> FC = std::nullopt) {
3204 // Check direct fields
3205 for (const FieldDecl *FD : CRD->fields()) {
3206 if (isSmartPtrType(FD->getType())) {
3207 if (!FC)
3208 return true;
3209 FC->consume(FD);
3210 }
3211 }
3212
3213 // Check fields from base classes
3214 for (const CXXBaseSpecifier &BaseSpec : CRD->bases()) {
3215 if (const CXXRecordDecl *BaseDecl =
3216 BaseSpec.getType()->getAsCXXRecordDecl()) {
3217 std::optional<FieldConsumer> NewFC;
3218 if (FC) {
3219 NewFC = FC->switchToBase(BaseDecl, BaseSpec.isVirtual());
3220 if (!NewFC)
3221 continue;
3222 }
3223 bool Found = hasSmartPtrField(BaseDecl, NewFC);
3224 if (Found && !FC)
3225 return true;
3226 }
3227 }
3228 return false;
3229}
3230
3231/// Check if an expression is an rvalue record type passed by value.
3232static bool isRvalueByValueRecord(const Expr *AE) {
3233 if (AE->isGLValue())
3234 return false;
3235
3236 QualType T = AE->getType();
3237 if (!T->isRecordType() || T->isReferenceType())
3238 return false;
3239
3240 // Accept common temp/construct forms but don't overfit.
3243}
3244
3245/// Check if an expression is an rvalue record with smart owning pointer fields
3246/// passed by value.
3248 if (!isRvalueByValueRecord(AE))
3249 return false;
3250
3251 const auto *CRD = AE->getType()->getAsCXXRecordDecl();
3252 return CRD && hasSmartPtrField(CRD);
3253}
3254
3255/// Check if a CXXRecordDecl has a name matching recognized smart pointer names.
3256static bool isSmartPtrRecord(const CXXRecordDecl *RD) {
3257 if (!RD)
3258 return false;
3259
3260 // Check the record name directly and accept both std and custom smart pointer
3261 // implementations for broader coverage
3262 return isSmartPtrName(RD->getName());
3263}
3264
3265/// Check if a call is a constructor of a smart owning pointer class that
3266/// accepts pointer parameters.
3267static bool isSmartPtrCall(const CallEvent &Call) {
3268 // Only check for smart pointer constructor calls
3269 const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(Call.getDecl());
3270 if (!CD)
3271 return false;
3272
3273 const auto *RD = CD->getParent();
3274 if (!isSmartPtrRecord(RD))
3275 return false;
3276
3277 // Check if constructor takes a pointer parameter
3278 for (const auto *Param : CD->parameters()) {
3279 QualType ParamType = Param->getType();
3280 if (ParamType->isPointerType() && !ParamType->isFunctionPointerType() &&
3281 !ParamType->isVoidPointerType()) {
3282 return true;
3283 }
3284 }
3285
3286 return false;
3287}
3288
3289/// Collect memory regions of smart owning pointer fields from a record type
3290/// (including fields from base classes).
3291static void
3294 llvm::SmallPtrSetImpl<const MemRegion *> &Out) {
3295 if (!Reg)
3296 return;
3297
3298 const auto *CRD = RecQT->getAsCXXRecordDecl();
3299 if (!CRD)
3300 return;
3301
3302 FieldConsumer FC{Reg, C, Out};
3303 hasSmartPtrField(CRD, FC);
3304}
3305
3306/// Handle smart pointer constructor calls by escaping allocated symbols
3307/// that are passed as pointer arguments to the constructor.
3308ProgramStateRef MallocChecker::handleSmartPointerConstructorArguments(
3309 const CallEvent &Call, ProgramStateRef State) const {
3310 const auto *CD = cast<CXXConstructorDecl>(Call.getDecl());
3311 for (unsigned I = 0, E = std::min(Call.getNumArgs(), CD->getNumParams());
3312 I != E; ++I) {
3313 const Expr *ArgExpr = Call.getArgExpr(I);
3314 if (!ArgExpr)
3315 continue;
3316
3317 QualType ParamType = CD->getParamDecl(I)->getType();
3318 if (ParamType->isPointerType() && !ParamType->isFunctionPointerType() &&
3319 !ParamType->isVoidPointerType()) {
3320 // This argument is a pointer being passed to smart pointer constructor
3321 SVal ArgVal = Call.getArgSVal(I);
3322 SymbolRef Sym = ArgVal.getAsSymbol();
3323 if (Sym && State->contains<RegionState>(Sym)) {
3324 const RefState *RS = State->get<RegionState>(Sym);
3325 if (RS && (RS->isAllocated() || RS->isAllocatedOfSizeZero())) {
3326 State = State->set<RegionState>(Sym, RefState::getEscaped(RS));
3327 }
3328 }
3329 }
3330 }
3331 return State;
3332}
3333
3334/// Handle all smart pointer related processing in function calls.
3335/// This includes both direct smart pointer constructor calls and by-value
3336/// arguments containing smart pointer fields.
3337ProgramStateRef MallocChecker::handleSmartPointerRelatedCalls(
3338 const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const {
3339
3340 // Handle direct smart pointer constructor calls first
3341 if (isSmartPtrCall(Call)) {
3342 return handleSmartPointerConstructorArguments(Call, State);
3343 }
3344
3345 // Handle smart pointer fields in by-value record arguments
3346 llvm::SmallPtrSet<const MemRegion *, 8> SmartPtrFieldRoots;
3347 for (unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) {
3348 const Expr *AE = Call.getArgExpr(I);
3349 if (!AE)
3350 continue;
3351 AE = AE->IgnoreParenImpCasts();
3352
3354 continue;
3355
3356 // Find a region for the argument.
3357 SVal ArgVal = Call.getArgSVal(I);
3358 const MemRegion *ArgRegion = ArgVal.getAsRegion();
3359 // Collect direct smart owning pointer field regions
3360 collectSmartPtrFieldRegions(ArgRegion, AE->getType(), C,
3361 SmartPtrFieldRoots);
3362 }
3363
3364 // Escape symbols reachable from smart pointer fields
3365 if (!SmartPtrFieldRoots.empty()) {
3366 SmallVector<const MemRegion *, 8> SmartPtrFieldRootsVec(
3367 SmartPtrFieldRoots.begin(), SmartPtrFieldRoots.end());
3368 State = EscapeTrackedCallback::EscapeTrackedRegionsReachableFrom(
3369 SmartPtrFieldRootsVec, State);
3370 }
3371
3372 return State;
3373}
3374
3375void MallocChecker::checkPostCall(const CallEvent &Call,
3376 CheckerContext &C) const {
3377 // Handle existing post-call handlers first
3378 if (const auto *PostFN = PostFnMap.lookup(Call)) {
3379 (*PostFN)(this, C.getState(), Call, C);
3380 return; // Post-handler already called addTransition, we're done
3381 }
3382
3383 // Handle smart pointer related processing only if no post-handler was called
3384 C.addTransition(handleSmartPointerRelatedCalls(Call, C, C.getState()));
3385}
3386
3387void MallocChecker::checkPreCall(const CallEvent &Call,
3388 CheckerContext &C) const {
3389
3390 if (const auto *DC = dyn_cast<CXXDeallocatorCall>(&Call)) {
3391 const CXXDeleteExpr *DE = DC->getOriginExpr();
3392
3393 // FIXME: I don't see a good reason for restricting the check against
3394 // use-after-free violations to the case when NewDeleteChecker is disabled.
3395 // (However, if NewDeleteChecker is enabled, perhaps it would be better to
3396 // do this check a bit later?)
3397 if (!NewDeleteChecker.isEnabled())
3398 if (SymbolRef Sym = C.getSVal(DE->getArgument()).getAsSymbol())
3399 checkUseAfterFree(Sym, C, DE->getArgument());
3400
3401 if (!isStandardNewDelete(DC->getDecl()))
3402 return;
3403
3404 ProgramStateRef State = C.getState();
3405 bool IsKnownToBeAllocated;
3406 State = FreeMemAux(
3407 C, DE->getArgument(), Call, State,
3408 /*Hold*/ false, IsKnownToBeAllocated,
3409 AllocationFamily(DE->isArrayForm() ? AF_CXXNewArray : AF_CXXNew));
3410
3411 C.addTransition(State);
3412 return;
3413 }
3414
3415 // If we see a `CXXDestructorCall` (that is, an _implicit_ destructor call)
3416 // to a region that's symbolic and known to be already freed, then it must be
3417 // implicitly triggered by a `delete` expression. In this situation we should
3418 // emit a `DoubleFree` report _now_ (before entering the call to the
3419 // destructor) because otherwise the destructor call can trigger a
3420 // use-after-free bug (by accessing any member variable) and that would be
3421 // (technically valid, but) less user-friendly report than the `DoubleFree`.
3422 if (const auto *DC = dyn_cast<CXXDestructorCall>(&Call)) {
3423 SymbolRef Sym = DC->getCXXThisVal().getAsSymbol();
3424 if (!Sym)
3425 return;
3426 if (isReleased(Sym, C)) {
3427 HandleDoubleFree(C, SourceRange(), /*Released=*/true, Sym,
3428 /*PrevSym=*/nullptr);
3429 return;
3430 }
3431 }
3432
3433 // We need to handle getline pre-conditions here before the pointed region
3434 // gets invalidated by StreamChecker
3435 if (const auto *PreFN = PreFnMap.lookup(Call)) {
3436 (*PreFN)(this, C.getState(), Call, C);
3437 return;
3438 }
3439
3440 // We will check for double free in the `evalCall` callback.
3441 // FIXME: It would be more logical to emit double free and use-after-free
3442 // reports via the same pathway (because double free is essentially a specia
3443 // case of use-after-free).
3444 if (const AnyFunctionCall *FC = dyn_cast<AnyFunctionCall>(&Call)) {
3445 const FunctionDecl *FD = FC->getDecl();
3446 if (!FD)
3447 return;
3448
3449 // FIXME: I suspect we should remove `MallocChecker.isEnabled() &&` because
3450 // it's fishy that the enabled/disabled state of one frontend may influence
3451 // reports produced by other frontends.
3452 if (MallocChecker.isEnabled() && isFreeingCall(Call))
3453 return;
3454 }
3455
3456 // Check if the callee of a method is deleted.
3457 if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) {
3458 SymbolRef Sym = CC->getCXXThisVal().getAsSymbol();
3459 if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr()))
3460 return;
3461 }
3462
3463 // Check arguments for being used after free.
3464 for (unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) {
3465 SVal ArgSVal = Call.getArgSVal(I);
3466 if (isa<Loc>(ArgSVal)) {
3467 SymbolRef Sym = ArgSVal.getAsSymbol(/*IncludeBaseRegions=*/true);
3468 if (!Sym)
3469 continue;
3470 if (checkUseAfterFree(Sym, C, Call.getArgExpr(I)))
3471 return;
3472 }
3473 }
3474}
3475
3476void MallocChecker::checkPreStmt(const ReturnStmt *S,
3477 CheckerContext &C) const {
3478 checkEscapeOnReturn(S, C);
3479}
3480
3481// In the CFG, automatic destructors come after the return statement.
3482// This callback checks for returning memory that is freed by automatic
3483// destructors, as those cannot be reached in checkPreStmt().
3484void MallocChecker::checkEndFunction(const ReturnStmt *S,
3485 CheckerContext &C) const {
3486 checkEscapeOnReturn(S, C);
3487}
3488
3489void MallocChecker::checkEscapeOnReturn(const ReturnStmt *S,
3490 CheckerContext &C) const {
3491 if (!S)
3492 return;
3493
3494 const Expr *E = S->getRetValue();
3495 if (!E)
3496 return;
3497
3498 // Check if we are returning a symbol.
3499 ProgramStateRef State = C.getState();
3500 SVal RetVal = C.getSVal(E);
3501 SymbolRef Sym = RetVal.getAsSymbol();
3502 if (!Sym)
3503 // If we are returning a field of the allocated struct or an array element,
3504 // the callee could still free the memory.
3505 if (const MemRegion *MR = RetVal.getAsRegion())
3507 if (const SymbolicRegion *BMR =
3508 dyn_cast<SymbolicRegion>(MR->getBaseRegion()))
3509 Sym = BMR->getSymbol();
3510
3511 // Check if we are returning freed memory.
3512 if (Sym)
3513 checkUseAfterFree(Sym, C, E);
3514}
3515
3516// TODO: Blocks should be either inlined or should call invalidate regions
3517// upon invocation. After that's in place, special casing here will not be
3518// needed.
3519void MallocChecker::checkPostStmt(const BlockExpr *BE,
3520 CheckerContext &C) const {
3521
3522 // Scan the BlockDecRefExprs for any object the retain count checker
3523 // may be tracking.
3524 if (!BE->getBlockDecl()->hasCaptures())
3525 return;
3526
3527 ProgramStateRef state = C.getState();
3528 const BlockDataRegion *R =
3529 cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
3530
3531 auto ReferencedVars = R->referenced_vars();
3532 if (ReferencedVars.empty())
3533 return;
3534
3535 SmallVector<const MemRegion*, 10> Regions;
3536 const LocationContext *LC = C.getLocationContext();
3537 MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
3538
3539 for (const auto &Var : ReferencedVars) {
3540 const VarRegion *VR = Var.getCapturedRegion();
3541 if (VR->getSuperRegion() == R) {
3542 VR = MemMgr.getVarRegion(VR->getDecl(), LC);
3543 }
3544 Regions.push_back(VR);
3545 }
3546
3547 state =
3548 state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
3549 C.addTransition(state);
3550}
3551
3553 assert(Sym);
3554 const RefState *RS = C.getState()->get<RegionState>(Sym);
3555 return (RS && RS->isReleased());
3556}
3557
3558bool MallocChecker::suppressDeallocationsInSuspiciousContexts(
3559 const CallEvent &Call, CheckerContext &C) const {
3560 if (Call.getNumArgs() == 0)
3561 return false;
3562
3563 StringRef FunctionStr = "";
3564 if (const auto *FD = dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl()))
3565 if (const Stmt *Body = FD->getBody())
3566 if (Body->getBeginLoc().isValid())
3567 FunctionStr =
3569 {FD->getBeginLoc(), Body->getBeginLoc()}),
3570 C.getSourceManager(), C.getLangOpts());
3571
3572 // We do not model the Integer Set Library's retain-count based allocation.
3573 if (!FunctionStr.contains("__isl_"))
3574 return false;
3575
3576 ProgramStateRef State = C.getState();
3577
3578 for (const Expr *Arg : cast<CallExpr>(Call.getOriginExpr())->arguments())
3579 if (SymbolRef Sym = C.getSVal(Arg).getAsSymbol())
3580 if (const RefState *RS = State->get<RegionState>(Sym))
3581 State = State->set<RegionState>(Sym, RefState::getEscaped(RS));
3582
3583 C.addTransition(State);
3584 return true;
3585}
3586
3587bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
3588 const Stmt *S) const {
3589
3590 if (isReleased(Sym, C)) {
3591 HandleUseAfterFree(C, S->getSourceRange(), Sym);
3592 return true;
3593 }
3594
3595 return false;
3596}
3597
3598void MallocChecker::checkUseZeroAllocated(SymbolRef Sym, CheckerContext &C,
3599 const Stmt *S) const {
3600 assert(Sym);
3601
3602 if (const RefState *RS = C.getState()->get<RegionState>(Sym)) {
3603 if (RS->isAllocatedOfSizeZero())
3604 HandleUseZeroAlloc(C, RS->getStmt()->getSourceRange(), Sym);
3605 }
3606 else if (C.getState()->contains<ReallocSizeZeroSymbols>(Sym)) {
3607 HandleUseZeroAlloc(C, S->getSourceRange(), Sym);
3608 }
3609}
3610
3611// Check if the location is a freed symbolic region.
3612void MallocChecker::checkLocation(SVal l, bool isLoad, const Stmt *S,
3613 CheckerContext &C) const {
3614 SymbolRef Sym = l.getLocSymbolInBase();
3615 if (Sym) {
3616 checkUseAfterFree(Sym, C, S);
3617 checkUseZeroAllocated(Sym, C, S);
3618 }
3619}
3620
3621// If a symbolic region is assumed to NULL (or another constant), stop tracking
3622// it - assuming that allocation failed on this path.
3623ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state,
3624 SVal Cond,
3625 bool Assumption) const {
3626 RegionStateTy RS = state->get<RegionState>();
3627 for (SymbolRef Sym : llvm::make_first_range(RS)) {
3628 // If the symbol is assumed to be NULL, remove it from consideration.
3629 ConstraintManager &CMgr = state->getConstraintManager();
3630 ConditionTruthVal AllocFailed = CMgr.isNull(state, Sym);
3631 if (AllocFailed.isConstrainedTrue())
3632 state = state->remove<RegionState>(Sym);
3633 }
3634
3635 // Realloc returns 0 when reallocation fails, which means that we should
3636 // restore the state of the pointer being reallocated.
3637 ReallocPairsTy RP = state->get<ReallocPairs>();
3638 for (auto [Sym, ReallocPair] : RP) {
3639 // If the symbol is assumed to be NULL, remove it from consideration.
3640 ConstraintManager &CMgr = state->getConstraintManager();
3641 ConditionTruthVal AllocFailed = CMgr.isNull(state, Sym);
3642 if (!AllocFailed.isConstrainedTrue())
3643 continue;
3644
3645 SymbolRef ReallocSym = ReallocPair.ReallocatedSym;
3646 if (const RefState *RS = state->get<RegionState>(ReallocSym)) {
3647 if (RS->isReleased()) {
3648 switch (ReallocPair.Kind) {
3649 case OAR_ToBeFreedAfterFailure:
3650 state = state->set<RegionState>(ReallocSym,
3651 RefState::getAllocated(RS->getAllocationFamily(), RS->getStmt()));
3652 break;
3653 case OAR_DoNotTrackAfterFailure:
3654 state = state->remove<RegionState>(ReallocSym);
3655 break;
3656 default:
3657 assert(ReallocPair.Kind == OAR_FreeOnFailure);
3658 }
3659 }
3660 }
3661 state = state->remove<ReallocPairs>(Sym);
3662 }
3663
3664 return state;
3665}
3666
3667bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
3668 const CallEvent *Call,
3669 ProgramStateRef State,
3670 SymbolRef &EscapingSymbol) const {
3671 assert(Call);
3672 EscapingSymbol = nullptr;
3673
3674 // For now, assume that any C++ or block call can free memory.
3675 // TODO: If we want to be more optimistic here, we'll need to make sure that
3676 // regions escape to C++ containers. They seem to do that even now, but for
3677 // mysterious reasons.
3679 return true;
3680
3681 // Check Objective-C messages by selector name.
3682 if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
3683 // If it's not a framework call, or if it takes a callback, assume it
3684 // can free memory.
3685 if (!Call->isInSystemHeader() || Call->argumentsMayEscape())
3686 return true;
3687
3688 // If it's a method we know about, handle it explicitly post-call.
3689 // This should happen before the "freeWhenDone" check below.
3691 return false;
3692
3693 // If there's a "freeWhenDone" parameter, but the method isn't one we know
3694 // about, we can't be sure that the object will use free() to deallocate the
3695 // memory, so we can't model it explicitly. The best we can do is use it to
3696 // decide whether the pointer escapes.
3697 if (std::optional<bool> FreeWhenDone = getFreeWhenDoneArg(*Msg))
3698 return *FreeWhenDone;
3699
3700 // If the first selector piece ends with "NoCopy", and there is no
3701 // "freeWhenDone" parameter set to zero, we know ownership is being
3702 // transferred. Again, though, we can't be sure that the object will use
3703 // free() to deallocate the memory, so we can't model it explicitly.
3704 StringRef FirstSlot = Msg->getSelector().getNameForSlot(0);
3705 if (FirstSlot.ends_with("NoCopy"))
3706 return true;
3707
3708 // If the first selector starts with addPointer, insertPointer,
3709 // or replacePointer, assume we are dealing with NSPointerArray or similar.
3710 // This is similar to C++ containers (vector); we still might want to check
3711 // that the pointers get freed by following the container itself.
3712 if (FirstSlot.starts_with("addPointer") ||
3713 FirstSlot.starts_with("insertPointer") ||
3714 FirstSlot.starts_with("replacePointer") ||
3715 FirstSlot == "valueWithPointer") {
3716 return true;
3717 }
3718
3719 // We should escape receiver on call to 'init'. This is especially relevant
3720 // to the receiver, as the corresponding symbol is usually not referenced
3721 // after the call.
3722 if (Msg->getMethodFamily() == OMF_init) {
3723 EscapingSymbol = Msg->getReceiverSVal().getAsSymbol();
3724 return true;
3725 }
3726
3727 // Otherwise, assume that the method does not free memory.
3728 // Most framework methods do not free memory.
3729 return false;
3730 }
3731
3732 // At this point the only thing left to handle is straight function calls.
3733 const FunctionDecl *FD = cast<SimpleFunctionCall>(Call)->getDecl();
3734 if (!FD)
3735 return true;
3736
3737 // If it's one of the allocation functions we can reason about, we model
3738 // its behavior explicitly.
3739 if (isMemCall(*Call))
3740 return false;
3741
3742 // If it's not a system call, assume it frees memory.
3743 if (!Call->isInSystemHeader())
3744 return true;
3745
3746 // White list the system functions whose arguments escape.
3747 const IdentifierInfo *II = FD->getIdentifier();
3748 if (!II)
3749 return true;
3750 StringRef FName = II->getName();
3751
3752 // White list the 'XXXNoCopy' CoreFoundation functions.
3753 // We specifically check these before
3754 if (FName.ends_with("NoCopy")) {
3755 // Look for the deallocator argument. We know that the memory ownership
3756 // is not transferred only if the deallocator argument is
3757 // 'kCFAllocatorNull'.
3758 for (unsigned i = 1; i < Call->getNumArgs(); ++i) {
3759 const Expr *ArgE = Call->getArgExpr(i)->IgnoreParenCasts();
3760 if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) {
3761 StringRef DeallocatorName = DE->getFoundDecl()->getName();
3762 if (DeallocatorName == "kCFAllocatorNull")
3763 return false;
3764 }
3765 }
3766 return true;
3767 }
3768
3769 // Associating streams with malloced buffers. The pointer can escape if
3770 // 'closefn' is specified (and if that function does free memory),
3771 // but it will not if closefn is not specified.
3772 // Currently, we do not inspect the 'closefn' function (PR12101).
3773 if (FName == "funopen")
3774 if (Call->getNumArgs() >= 4 && Call->getArgSVal(4).isConstant(0))
3775 return false;
3776
3777 // Do not warn on pointers passed to 'setbuf' when used with std streams,
3778 // these leaks might be intentional when setting the buffer for stdio.
3779 // http://stackoverflow.com/questions/2671151/who-frees-setvbuf-buffer
3780 if (FName == "setbuf" || FName =="setbuffer" ||
3781 FName == "setlinebuf" || FName == "setvbuf") {
3782 if (Call->getNumArgs() >= 1) {
3783 const Expr *ArgE = Call->getArgExpr(0)->IgnoreParenCasts();
3784 if (const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE))
3785 if (const VarDecl *D = dyn_cast<VarDecl>(ArgDRE->getDecl()))
3786 if (D->getCanonicalDecl()->getName().contains("std"))
3787 return true;
3788 }
3789 }
3790
3791 // A bunch of other functions which either take ownership of a pointer or
3792 // wrap the result up in a struct or object, meaning it can be freed later.
3793 // (See RetainCountChecker.) Not all the parameters here are invalidated,
3794 // but the Malloc checker cannot differentiate between them. The right way
3795 // of doing this would be to implement a pointer escapes callback.
3796 if (FName == "CGBitmapContextCreate" ||
3797 FName == "CGBitmapContextCreateWithData" ||
3798 FName == "CVPixelBufferCreateWithBytes" ||
3799 FName == "CVPixelBufferCreateWithPlanarBytes" ||
3800 FName == "OSAtomicEnqueue") {
3801 return true;
3802 }
3803
3804 if (FName == "postEvent" &&
3805 FD->getQualifiedNameAsString() == "QCoreApplication::postEvent") {
3806 return true;
3807 }
3808
3809 if (FName == "connectImpl" &&
3810 FD->getQualifiedNameAsString() == "QObject::connectImpl") {
3811 return true;
3812 }
3813
3814 if (FName == "singleShotImpl" &&
3815 FD->getQualifiedNameAsString() == "QTimer::singleShotImpl") {
3816 return true;
3817 }
3818
3819 // Protobuf function declared in `generated_message_util.h` that takes
3820 // ownership of the second argument. As the first and third arguments are
3821 // allocation arenas and won't be tracked by this checker, there is no reason
3822 // to set `EscapingSymbol`. (Also, this is an implementation detail of
3823 // Protobuf, so it's better to be a bit more permissive.)
3824 if (FName == "GetOwnedMessageInternal") {
3825 return true;
3826 }
3827
3828 // Handle cases where we know a buffer's /address/ can escape.
3829 // Note that the above checks handle some special cases where we know that
3830 // even though the address escapes, it's still our responsibility to free the
3831 // buffer.
3832 if (Call->argumentsMayEscape())
3833 return true;
3834
3835 // Otherwise, assume that the function does not free memory.
3836 // Most system calls do not free the memory.
3837 return false;
3838}
3839
3840ProgramStateRef MallocChecker::checkPointerEscape(ProgramStateRef State,
3841 const InvalidatedSymbols &Escaped,
3842 const CallEvent *Call,
3843 PointerEscapeKind Kind) const {
3844 return checkPointerEscapeAux(State, Escaped, Call, Kind,
3845 /*IsConstPointerEscape*/ false);
3846}
3847
3848ProgramStateRef MallocChecker::checkConstPointerEscape(ProgramStateRef State,
3849 const InvalidatedSymbols &Escaped,
3850 const CallEvent *Call,
3851 PointerEscapeKind Kind) const {
3852 // If a const pointer escapes, it may not be freed(), but it could be deleted.
3853 return checkPointerEscapeAux(State, Escaped, Call, Kind,
3854 /*IsConstPointerEscape*/ true);
3855}
3856
3857static bool checkIfNewOrNewArrayFamily(const RefState *RS) {
3858 return (RS->getAllocationFamily().Kind == AF_CXXNewArray ||
3859 RS->getAllocationFamily().Kind == AF_CXXNew);
3860}
3861
3862ProgramStateRef MallocChecker::checkPointerEscapeAux(
3863 ProgramStateRef State, const InvalidatedSymbols &Escaped,
3864 const CallEvent *Call, PointerEscapeKind Kind,
3865 bool IsConstPointerEscape) const {
3866 // If we know that the call does not free memory, or we want to process the
3867 // call later, keep tracking the top level arguments.
3868 SymbolRef EscapingSymbol = nullptr;
3869 if (Kind == PSK_DirectEscapeOnCall &&
3870 !mayFreeAnyEscapedMemoryOrIsModeledExplicitly(Call, State,
3871 EscapingSymbol) &&
3872 !EscapingSymbol) {
3873 return State;
3874 }
3875
3876 for (SymbolRef sym : Escaped) {
3877 if (EscapingSymbol && EscapingSymbol != sym)
3878 continue;
3879
3880 if (const RefState *RS = State->get<RegionState>(sym))
3881 if (RS->isAllocated() || RS->isAllocatedOfSizeZero())
3882 if (!IsConstPointerEscape || checkIfNewOrNewArrayFamily(RS))
3883 State = State->set<RegionState>(sym, RefState::getEscaped(RS));
3884 }
3885 return State;
3886}
3887
3888bool MallocChecker::isArgZERO_SIZE_PTR(ProgramStateRef State, CheckerContext &C,
3889 SVal ArgVal) const {
3890 if (!KernelZeroSizePtrValue)
3891 KernelZeroSizePtrValue =
3892 tryExpandAsInteger("ZERO_SIZE_PTR", C.getPreprocessor());
3893
3894 const llvm::APSInt *ArgValKnown =
3895 C.getSValBuilder().getKnownValue(State, ArgVal);
3896 return ArgValKnown && *KernelZeroSizePtrValue &&
3897 ArgValKnown->getSExtValue() == **KernelZeroSizePtrValue;
3898}
3899
3901 ProgramStateRef prevState) {
3902 ReallocPairsTy currMap = currState->get<ReallocPairs>();
3903 ReallocPairsTy prevMap = prevState->get<ReallocPairs>();
3904
3905 for (const ReallocPairsTy::value_type &Pair : prevMap) {
3906 SymbolRef sym = Pair.first;
3907 if (!currMap.lookup(sym))
3908 return sym;
3909 }
3910
3911 return nullptr;
3912}
3913
3915 if (const IdentifierInfo *II = DD->getParent()->getIdentifier()) {
3916 StringRef N = II->getName();
3917 if (N.contains_insensitive("ptr") || N.contains_insensitive("pointer")) {
3918 if (N.contains_insensitive("ref") || N.contains_insensitive("cnt") ||
3919 N.contains_insensitive("intrusive") ||
3920 N.contains_insensitive("shared") || N.ends_with_insensitive("rc")) {
3921 return true;
3922 }
3923 }
3924 }
3925 return false;
3926}
3927
3928PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
3929 BugReporterContext &BRC,
3930 PathSensitiveBugReport &BR) {
3931 ProgramStateRef state = N->getState();
3932 ProgramStateRef statePrev = N->getFirstPred()->getState();
3933
3934 const RefState *RSCurr = state->get<RegionState>(Sym);
3935 const RefState *RSPrev = statePrev->get<RegionState>(Sym);
3936
3937 const Stmt *S = N->getStmtForDiagnostics();
3938 // When dealing with containers, we sometimes want to give a note
3939 // even if the statement is missing.
3940 if (!S && (!RSCurr || RSCurr->getAllocationFamily().Kind != AF_InnerBuffer))
3941 return nullptr;
3942
3943 const LocationContext *CurrentLC = N->getLocationContext();
3944
3945 // If we find an atomic fetch_add or fetch_sub within the function in which
3946 // the pointer was released (before the release), this is likely a release
3947 // point of reference-counted object (like shared pointer).
3948 //
3949 // Because we don't model atomics, and also because we don't know that the
3950 // original reference count is positive, we should not report use-after-frees
3951 // on objects deleted in such functions. This can probably be improved
3952 // through better shared pointer modeling.
3953 if (ReleaseFunctionLC && (ReleaseFunctionLC == CurrentLC ||
3954 ReleaseFunctionLC->isParentOf(CurrentLC))) {
3955 if (const auto *AE = dyn_cast<AtomicExpr>(S)) {
3956 // Check for manual use of atomic builtins.
3957 AtomicExpr::AtomicOp Op = AE->getOp();
3958 if (Op == AtomicExpr::AO__c11_atomic_fetch_add ||
3959 Op == AtomicExpr::AO__c11_atomic_fetch_sub) {
3960 BR.markInvalid(getTag(), S);
3961 // After report is considered invalid there is no need to proceed
3962 // futher.
3963 return nullptr;
3964 }
3965 } else if (const auto *CE = dyn_cast<CallExpr>(S)) {
3966 // Check for `std::atomic` and such. This covers both regular method calls
3967 // and operator calls.
3968 if (const auto *MD =
3969 dyn_cast_or_null<CXXMethodDecl>(CE->getDirectCallee())) {
3970 const CXXRecordDecl *RD = MD->getParent();
3971 // A bit wobbly with ".contains()" because it may be like
3972 // "__atomic_base" or something.
3973 if (StringRef(RD->getNameAsString()).contains("atomic")) {
3974 BR.markInvalid(getTag(), S);
3975 // After report is considered invalid there is no need to proceed
3976 // futher.
3977 return nullptr;
3978 }
3979 }
3980 }
3981 }
3982
3983 // FIXME: We will eventually need to handle non-statement-based events
3984 // (__attribute__((cleanup))).
3985
3986 // Find out if this is an interesting point and what is the kind.
3987 StringRef Msg;
3988 std::unique_ptr<StackHintGeneratorForSymbol> StackHint = nullptr;
3989 SmallString<256> Buf;
3990 llvm::raw_svector_ostream OS(Buf);
3991
3992 if (Mode == Normal) {
3993 if (isAllocated(RSCurr, RSPrev, S)) {
3994 Msg = "Memory is allocated";
3995 StackHint = std::make_unique<StackHintGeneratorForSymbol>(
3996 Sym, "Returned allocated memory");
3997 } else if (isReleased(RSCurr, RSPrev, S)) {
3998 const auto Family = RSCurr->getAllocationFamily();
3999 switch (Family.Kind) {
4000 case AF_Alloca:
4001 case AF_Malloc:
4002 case AF_Custom:
4003 case AF_CXXNew:
4004 case AF_CXXNewArray:
4005 case AF_IfNameIndex:
4006 Msg = "Memory is released";
4007 StackHint = std::make_unique<StackHintGeneratorForSymbol>(
4008 Sym, "Returning; memory was released");
4009 break;
4010 case AF_InnerBuffer: {
4011 const MemRegion *ObjRegion =
4013 const auto *TypedRegion = cast<TypedValueRegion>(ObjRegion);
4014 QualType ObjTy = TypedRegion->getValueType();
4015 OS << "Inner buffer of '" << ObjTy << "' ";
4016
4018 OS << "deallocated by call to destructor";
4019 StackHint = std::make_unique<StackHintGeneratorForSymbol>(
4020 Sym, "Returning; inner buffer was deallocated");
4021 } else {
4022 OS << "reallocated by call to '";
4023 const Stmt *S = RSCurr->getStmt();
4024 if (const auto *MemCallE = dyn_cast<CXXMemberCallExpr>(S)) {
4025 OS << MemCallE->getMethodDecl()->getDeclName();
4026 } else if (const auto *OpCallE = dyn_cast<CXXOperatorCallExpr>(S)) {
4027 OS << OpCallE->getDirectCallee()->getDeclName();
4028 } else if (const auto *CallE = dyn_cast<CallExpr>(S)) {
4029 auto &CEMgr = BRC.getStateManager().getCallEventManager();
4030 CallEventRef<> Call =
4031 CEMgr.getSimpleCall(CallE, state, CurrentLC, {nullptr, 0});
4032 if (const auto *D = dyn_cast_or_null<NamedDecl>(Call->getDecl()))
4033 OS << D->getDeclName();
4034 else
4035 OS << "unknown";
4036 }
4037 OS << "'";
4038 StackHint = std::make_unique<StackHintGeneratorForSymbol>(
4039 Sym, "Returning; inner buffer was reallocated");
4040 }
4041 Msg = OS.str();
4042 break;
4043 }
4044 case AF_None:
4045 assert(false && "Unhandled allocation family!");
4046 return nullptr;
4047 }
4048
4049 // Record the stack frame that is _responsible_ for this memory release
4050 // event. This will be used by the false positive suppression heuristics
4051 // that recognize the release points of reference-counted objects.
4052 //
4053 // Usually (e.g. in C) we say that the _responsible_ stack frame is the
4054 // current innermost stack frame:
4055 ReleaseFunctionLC = CurrentLC->getStackFrame();
4056 // ...but if the stack contains a destructor call, then we say that the
4057 // outermost destructor stack frame is the _responsible_ one:
4058 for (const LocationContext *LC = CurrentLC; LC; LC = LC->getParent()) {
4059 if (const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) {
4061 // This immediately looks like a reference-counting destructor.
4062 // We're bad at guessing the original reference count of the
4063 // object, so suppress the report for now.
4064 BR.markInvalid(getTag(), DD);
4065
4066 // After report is considered invalid there is no need to proceed
4067 // futher.
4068 return nullptr;
4069 }
4070
4071 // Switch suspection to outer destructor to catch patterns like:
4072 // (note that class name is distorted to bypass
4073 // isReferenceCountingPointerDestructor() logic)
4074 //
4075 // SmartPointr::~SmartPointr() {
4076 // if (refcount.fetch_sub(1) == 1)
4077 // release_resources();
4078 // }
4079 // void SmartPointr::release_resources() {
4080 // free(buffer);
4081 // }
4082 //
4083 // This way ReleaseFunctionLC will point to outermost destructor and
4084 // it would be possible to catch wider range of FP.
4085 //
4086 // NOTE: it would be great to support smth like that in C, since
4087 // currently patterns like following won't be supressed:
4088 //
4089 // void doFree(struct Data *data) { free(data); }
4090 // void putData(struct Data *data)
4091 // {
4092 // if (refPut(data))
4093 // doFree(data);
4094 // }
4095 ReleaseFunctionLC = LC->getStackFrame();
4096 }
4097 }
4098
4099 } else if (isRelinquished(RSCurr, RSPrev, S)) {
4100 Msg = "Memory ownership is transferred";
4101 StackHint = std::make_unique<StackHintGeneratorForSymbol>(Sym, "");
4102 } else if (hasReallocFailed(RSCurr, RSPrev, S)) {
4103 Mode = ReallocationFailed;
4104 Msg = "Reallocation failed";
4105 StackHint = std::make_unique<StackHintGeneratorForReallocationFailed>(
4106 Sym, "Reallocation failed");
4107
4108 if (SymbolRef sym = findFailedReallocSymbol(state, statePrev)) {
4109 // Is it possible to fail two reallocs WITHOUT testing in between?
4110 assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
4111 "We only support one failed realloc at a time.");
4112 BR.markInteresting(sym);
4113 FailedReallocSymbol = sym;
4114 }
4115 }
4116
4117 // We are in a special mode if a reallocation failed later in the path.
4118 } else if (Mode == ReallocationFailed) {
4119 assert(FailedReallocSymbol && "No symbol to look for.");
4120
4121 // Is this is the first appearance of the reallocated symbol?
4122 if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
4123 // We're at the reallocation point.
4124 Msg = "Attempt to reallocate memory";
4125 StackHint = std::make_unique<StackHintGeneratorForSymbol>(
4126 Sym, "Returned reallocated memory");
4127 FailedReallocSymbol = nullptr;
4128 Mode = Normal;
4129 }
4130 }
4131
4132 if (Msg.empty()) {
4133 assert(!StackHint);
4134 return nullptr;
4135 }
4136
4137 assert(StackHint);
4138
4139 // Generate the extra diagnostic.
4140 PathDiagnosticLocation Pos;
4141 if (!S) {
4142 assert(RSCurr->getAllocationFamily().Kind == AF_InnerBuffer);
4143 auto PostImplCall = N->getLocation().getAs<PostImplicitCall>();
4144 if (!PostImplCall)
4145 return nullptr;
4146 Pos = PathDiagnosticLocation(PostImplCall->getLocation(),
4147 BRC.getSourceManager());
4148 } else {
4149 Pos = PathDiagnosticLocation(S, BRC.getSourceManager(),
4150 N->getLocationContext());
4151 }
4152
4153 auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, Msg, true);
4154 BR.addCallStackHint(P, std::move(StackHint));
4155 return P;
4156}
4157
4158void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State,
4159 const char *NL, const char *Sep) const {
4160
4161 RegionStateTy RS = State->get<RegionState>();
4162
4163 if (!RS.isEmpty()) {
4164 Out << Sep << "MallocChecker :" << NL;
4165 for (auto [Sym, Data] : RS) {
4166 const RefState *RefS = State->get<RegionState>(Sym);
4167 AllocationFamily Family = RefS->getAllocationFamily();
4168
4169 const CheckerFrontend *Frontend =
4170 getRelevantFrontendAs<CheckerFrontend>(Family);
4171
4172 Sym->dumpToStream(Out);
4173 Out << " : ";
4174 Data.dump(Out);
4175 if (Frontend && Frontend->isEnabled())
4176 Out << " (" << Frontend->getName() << ")";
4177 Out << NL;
4178 }
4179 }
4180}
4181
4182namespace clang {
4183namespace ento {
4184namespace allocation_state {
4185
4187markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin) {
4188 AllocationFamily Family(AF_InnerBuffer);
4189 return State->set<RegionState>(Sym, RefState::getReleased(Family, Origin));
4190}
4191
4192} // end namespace allocation_state
4193} // end namespace ento
4194} // end namespace clang
4195
4196// Intended to be used in InnerPointerChecker to register the part of
4197// MallocChecker connected to it.
4199 Mgr.getChecker<MallocChecker>()->InnerPointerChecker.enable(Mgr);
4200}
4201
4202void ento::registerDynamicMemoryModeling(CheckerManager &Mgr) {
4203 auto *Chk = Mgr.getChecker<MallocChecker>();
4204 // FIXME: This is a "hidden" undocumented frontend but there are public
4205 // checker options which are attached to it.
4206 CheckerNameRef DMMName = Mgr.getCurrentCheckerName();
4207 Chk->ShouldIncludeOwnershipAnnotatedFunctions =
4208 Mgr.getAnalyzerOptions().getCheckerBooleanOption(DMMName, "Optimistic");
4209 Chk->ShouldRegisterNoOwnershipChangeVisitor =
4210 Mgr.getAnalyzerOptions().getCheckerBooleanOption(
4211 DMMName, "AddNoOwnershipChangeNotes");
4212}
4213
4214bool ento::shouldRegisterDynamicMemoryModeling(const CheckerManager &mgr) {
4215 return true;
4216}
4217
4218#define REGISTER_CHECKER(NAME) \
4219 void ento::register##NAME(CheckerManager &Mgr) { \
4220 Mgr.getChecker<MallocChecker>()->NAME.enable(Mgr); \
4221 } \
4222 \
4223 bool ento::shouldRegister##NAME(const CheckerManager &) { return true; }
4224
4225// TODO: NewDelete and NewDeleteLeaks shouldn't be registered when not in C++.
4226REGISTER_CHECKER(MallocChecker)
4227REGISTER_CHECKER(NewDeleteChecker)
4228REGISTER_CHECKER(NewDeleteLeaksChecker)
4229REGISTER_CHECKER(MismatchedDeallocatorChecker)
4230REGISTER_CHECKER(TaintedAllocChecker)
#define V(N, I)
#define REGISTER_CHECKER(name)
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Defines the clang::Expr interface and subclasses for C++ expressions.
#define X(type, name)
Definition Value.h:97
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::MachO::Target Target
Definition MachO.h:51
static bool isRvalueByValueRecordWithSmartPtr(const Expr *AE)
Check if an expression is an rvalue record with smart owning pointer fields passed by value.
static bool isFromStdNamespace(const CallEvent &Call)
static bool isStandardNew(const FunctionDecl *FD)
static bool hasNonTrivialConstructorCall(const CXXNewExpr *NE)
static QualType getDeepPointeeType(QualType T)
static bool isReleased(SymbolRef Sym, CheckerContext &C)
Check if the memory associated with this symbol was released.
static void printExpectedAllocName(raw_ostream &os, AllocationFamily Family)
Print expected name of an allocator based on the deallocator's family derived from the DeallocExpr.
static void collectSmartPtrFieldRegions(const MemRegion *Reg, QualType RecQT, CheckerContext &C, llvm::SmallPtrSetImpl< const MemRegion * > &Out)
Collect memory regions of smart owning pointer fields from a record type (including fields from base ...
static bool hasSmartPtrField(const CXXRecordDecl *CRD, std::optional< FieldConsumer > FC=std::nullopt)
Check if a record type has smart owning pointer fields (directly or in base classes).
static bool isStandardDelete(const FunctionDecl *FD)
static bool isReferenceCountingPointerDestructor(const CXXDestructorDecl *DD)
static bool isSmartPtrType(QualType QT)
static bool isStandardNewDelete(const T &FD)
Tells if the callee is one of the builtin new/delete operators, including placement operators and oth...
static SymbolRef findFailedReallocSymbol(ProgramStateRef currState, ProgramStateRef prevState)
static bool isRvalueByValueRecord(const Expr *AE)
Check if an expression is an rvalue record type passed by value.
#define BUGTYPE_PROVIDER(NAME, DEF)
static bool isGRealloc(const CallEvent &Call)
static const Expr * getPlacementNewBufferArg(const CallExpr *CE, const FunctionDecl *FD)
#define CASE(ID)
static bool isSmartPtrRecord(const CXXRecordDecl *RD)
Check if a CXXRecordDecl has a name matching recognized smart pointer names.
#define CHECK_FN(NAME)
static void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family)
Print expected name of a deallocator based on the allocator's family.
static bool isStandardRealloc(const CallEvent &Call)
static bool isSmartPtrCall(const CallEvent &Call)
Check if a call is a constructor of a smart owning pointer class that accepts pointer parameters.
static bool didPreviousFreeFail(ProgramStateRef State, SymbolRef Sym, SymbolRef &RetStatusSymbol)
Checks if the previous call to free on the given symbol failed - if free failed, returns true.
static ProgramStateRef MallocUpdateRefState(CheckerContext &C, const Expr *E, ProgramStateRef State, AllocationFamily Family, std::optional< SVal > RetVal=std::nullopt)
Update the RefState to reflect the new memory allocation.
static bool printMemFnName(raw_ostream &os, CheckerContext &C, const Expr *E)
Print names of allocators and deallocators.
static bool isSmartPtrName(StringRef Name)
static void printOwnershipTakesList(raw_ostream &os, CheckerContext &C, const Expr *E)
static bool isKnownDeallocObjCMethodName(const ObjCMethodCall &Call)
static std::optional< bool > getFreeWhenDoneArg(const ObjCMethodCall &Call)
static bool checkIfNewOrNewArrayFamily(const RefState *RS)
#define SM(sm)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set of type NameTy, suitable for placement into the ProgramState.
Defines the SourceManager interface.
__DEVICE__ long long abs(long long __n)
__device__ __2f16 float __ockl_bool s
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
SourceManager & getSourceManager()
Definition ASTContext.h:845
CanQualType VoidPtrTy
CanQualType getCanonicalSizeType() const
CanQualType UnsignedLongTy
CanQualType CharTy
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:903
bool hasCaptures() const
True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...
Definition Decl.h:4773
const BlockDecl * getBlockDecl() const
Definition Expr.h:6570
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents binding an expression to a temporary.
Definition ExprCXX.h:1494
Represents a call to a C++ constructor.
Definition ExprCXX.h:1549
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Definition ExprCXX.h:1612
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2628
bool isArrayForm() const
Definition ExprCXX.h:2654
Represents a C++ destructor within a class.
Definition DeclCXX.h:2869
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2255
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2357
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
base_class_range bases()
Definition DeclCXX.h:608
Represents a C++ functional cast expression that builds a temporary object.
Definition ExprCXX.h:1901
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3081
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3060
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3068
static CharSourceRange getTokenRange(SourceRange R)
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isInStdNamespace() const
Definition DeclBase.cpp:449
bool hasAttrs() const
Definition DeclBase.h:518
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:546
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:559
SourceLocation getLocation() const
Definition DeclBase.h:439
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
This represents one expression.
Definition Expr.h:112
bool isGLValue() const
Definition Expr.h:287
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3093
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3088
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3160
Represents a function declaration or definition.
Definition Decl.h:2000
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2797
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition Decl.cpp:3268
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2774
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
Definition Decl.h:2933
OverloadedOperatorKind getOverloadedOperator() const
getOverloadedOperator - Which C++ overloaded operator this function represents, if any.
Definition Decl.cpp:4119
QualType getDeclaredReturnType() const
Get the declared return type, which may differ from the actual return type if the return type is dedu...
Definition Decl.h:2862
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3188
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition Expr.h:3787
Describes an C or C++ initializer list.
Definition Expr.h:5233
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
Definition Lexer.cpp:1020
bool isParentOf(const LocationContext *LC) const
const Decl * getDecl() const
const LocationContext * getParent() const
It might return null.
const StackFrameContext * getStackFrame() const
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4922
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
std::string getQualifiedNameAsString() const
Definition Decl.cpp:1680
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition Decl.h:317
An expression that sends a message to the given Objective-C object or class.
Definition ExprObjC.h:940
bool isConsumedExpr(Expr *E) const
Kind getKind() const
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
field_range fields() const
Definition Decl.h:4515
Expr * getRetValue()
Definition Stmt.h:3167
Smart pointer class that efficiently represents Objective-C method names.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
unsigned getNumArgs() const
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
The base class of all kinds of template declarations (e.g., class, function, etc.).
NamedDecl * getTemplatedDecl() const
Get the underlying, templated declaration.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isVoidPointerType() const
Definition Type.cpp:712
bool isFunctionPointerType() const
Definition TypeBase.h:8582
bool isPointerType() const
Definition TypeBase.h:8515
CanQualType getCanonicalTypeUnqualified() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
QualType getType() const
Definition Decl.h:723
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1208
APSIntPtr getMaxValue(const llvm::APSInt &v)
llvm::iterator_range< referenced_vars_iterator > referenced_vars() const
StringRef getDescription() const
A verbose warning message that is appropriate for displaying next to the source code that introduces ...
ProgramStateManager & getStateManager() const
const SourceManager & getSourceManager() const
BugReporterVisitors are used to add custom diagnostics along a path.
An immutable map from CallDescriptions to arbitrary data.
CallEventRef getSimpleCall(const CallExpr *E, ProgramStateRef State, const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef)
Represents an abstract call to a function or method along a particular path.
Definition CallEvent.h:153
Checker families (where a single backend class implements multiple related frontends) should derive f...
Definition Checker.h:584
A CheckerFrontend instance is what the user recognizes as "one checker": it has a public canonical na...
Definition Checker.h:514
CheckerNameRef getName() const
Definition Checker.h:524
const AnalyzerOptions & getAnalyzerOptions() const
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 ...
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym)
Convenience method to query the state to see if a symbol is null or not null, or if neither assumptio...
const ProgramStateRef & getState() const
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
const LocationContext * getLocationContext() const
ExplodedNode * getFirstPred()
static bool isLocType(QualType T)
Definition SVals.h:262
const VarRegion * getVarRegion(const VarDecl *VD, const LocationContext *LC)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and LocationC...
MemRegion - The root abstract class for all memory regions.
Definition MemRegion.h:98
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const
bool hasMemorySpace(ProgramStateRef State) const
Definition MemRegion.h:148
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace(ProgramStateRef State) const
Returns the most specific memory space for this memory region in the given ProgramStateRef.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
const RegionTy * getAs() const
Definition MemRegion.h:1416
Kind getKind() const
Definition MemRegion.h:203
virtual bool canPrintPretty() const
Returns true if this region can be printed in a user-friendly way.
Represents any expression that calls an Objective-C method.
Definition CallEvent.h:1261
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind=bugreporter::TrackingKind::Thorough)
Marks a symbol as interesting.
PathDiagnosticLocation getLocation() const override
The primary location of the bug report that points at the undesirable behavior in the code.
void addCallStackHint(PathDiagnosticPieceRef Piece, std::unique_ptr< StackHintGenerator > StackHint)
void markInvalid(const void *Tag, const void *Data)
Marks the current report as invalid, meaning that it is probably a false positive and should not be r...
CallEventManager & getCallEventManager()
bool hasSymbolicOffset() const
Definition MemRegion.h:83
int64_t getOffset() const
Definition MemRegion.h:85
DefinedSVal getConjuredHeapSymbolVal(ConstCFGElementRef elem, const LocationContext *LCtx, QualType type, unsigned Count)
Conjure a symbol representing heap allocated memory region.
DefinedOrUnknownSVal makeZeroVal(QualType type)
Construct an SVal representing '0' for the specified type.
BasicValueFactory & getBasicValueFactory()
ASTContext & getContext()
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0
Create a new value which represents a binary expression with two non- location operands.
QualType getConditionType() const
SVal evalEQ(ProgramStateRef state, SVal lhs, SVal rhs)
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
loc::MemRegionVal getAllocaRegionVal(const Expr *E, const LocationContext *LCtx, unsigned Count)
Create an SVal representing the result of an alloca()-like call, that is, an AllocaRegion on the stac...
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
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
Definition SVals.cpp:103
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
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
Definition SVals.cpp:67
const MemRegion * getAsRegion() const
Definition SVals.cpp:119
SymbolRef getLocSymbolInBase() const
Get the symbol in the SVal or its base region.
Definition SVals.cpp:79
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition SVals.h:83
SubRegion - A region that subsets another larger region.
Definition MemRegion.h:474
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
Definition MemRegion.h:487
virtual void dumpToStream(raw_ostream &os) const
Definition SymExpr.h:81
virtual QualType getType() const =0
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
SymbolRef getSymbol() const
It might return null.
Definition MemRegion.h:827
const VarDecl * getDecl() const override=0
const StackFrameContext * getStackFrame() const
It might return null.
Defines the clang::TargetInfo interface.
__inline void unsigned int _2
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXDeleteExpr > cxxDeleteExpr
Matches delete expressions.
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
internal::Matcher< T > findAll(const internal::Matcher< T > &Matcher)
Matches if the node or any descendant matches.
const internal::VariadicAllOfMatcher< Stmt > stmt
Matches statements.
const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits< unsigned >::max()> anyOf
Matches if any of the given matchers matches.
ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin)
std::unique_ptr< BugReporterVisitor > getInnerPointerBRVisitor(SymbolRef Sym)
This function provides an additional visitor that augments the bug report with information relevant t...
const MemRegion * getContainerObjRegion(ProgramStateRef State, SymbolRef Sym)
'Sym' represents a pointer to the inner buffer of a container object.
std::vector< SymbolRef > getTaintedSymbols(ProgramStateRef State, const Stmt *S, const LocationContext *LCtx, TaintTagType Kind=TaintTagGeneric)
Returns the tainted Symbols for a given Statement and state.
Definition Taint.cpp:170
PointerEscapeKind
Describes the different reasons a pointer escapes during analysis.
@ PSK_DirectEscapeOnCall
The pointer has been passed to a function call directly.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition Store.h:51
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
Definition SymExpr.h:133
ProgramStateRef setDynamicExtent(ProgramStateRef State, const MemRegion *MR, DefinedOrUnknownSVal Extent)
Set the dynamic extent Extent of the region MR.
void registerInnerPointerCheckerAux(CheckerManager &Mgr)
Register the part of MallocChecker connected to InnerPointerChecker.
@ 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.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
bool NE(InterpState &S, CodePtr OpPC)
Definition Interp.h:1235
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
Definition Sema.h:816
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition CallGraph.h:204
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
Expr * Cond
};
const FunctionProtoType * T
bool operator!=(CanQual< T > x, CanQual< U > y)
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword.
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Other
Other implicit parameter.
Definition Decl.h:1746
int const char * function
Definition c++config.h:31
Helper struct for collecting smart owning pointer field regions.
void consume(const FieldDecl *FD)
std::optional< FieldConsumer > switchToBase(const CXXRecordDecl *BaseDecl, bool IsVirtual)
FieldConsumer(const MemRegion *Reg, CheckerContext &C, llvm::SmallPtrSetImpl< const MemRegion * > &Out)
llvm::SmallPtrSetImpl< const MemRegion * > * Out
CheckerContext * C
const MemRegion * Reg