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