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