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