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