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