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