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