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