1218887Sdim//=== MallocChecker.cpp - A malloc/free checker -------------------*- C++ -*--//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10218887Sdim// This file defines malloc/free checker, which checks for potential memory
11218887Sdim// leaks, double free, and use-after-free problems.
12218887Sdim//
13218887Sdim//===----------------------------------------------------------------------===//
14218887Sdim
15221345Sdim#include "ClangSACheckers.h"
16234353Sdim#include "InterCheckerAPI.h"
17249423Sdim#include "clang/AST/Attr.h"
18249423Sdim#include "clang/Basic/SourceManager.h"
19249423Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
20221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h"
21221345Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h"
22249423Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
23221345Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
24226633Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
25226633Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
26218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
27218887Sdim#include "llvm/ADT/ImmutableMap.h"
28249423Sdim#include "llvm/ADT/STLExtras.h"
29234353Sdim#include "llvm/ADT/SmallString.h"
30243830Sdim#include "llvm/ADT/StringExtras.h"
31234353Sdim#include <climits>
32234353Sdim
33218887Sdimusing namespace clang;
34218887Sdimusing namespace ento;
35218887Sdim
36218887Sdimnamespace {
37218887Sdim
38249423Sdim// Used to check correspondence between allocators and deallocators.
39249423Sdimenum AllocationFamily {
40249423Sdim  AF_None,
41249423Sdim  AF_Malloc,
42249423Sdim  AF_CXXNew,
43249423Sdim  AF_CXXNewArray
44249423Sdim};
45249423Sdim
46218887Sdimclass RefState {
47239462Sdim  enum Kind { // Reference to allocated memory.
48239462Sdim              Allocated,
49239462Sdim              // Reference to released/freed memory.
50239462Sdim              Released,
51239462Sdim              // The responsibility for freeing resources has transfered from
52239462Sdim              // this reference. A relinquished symbol should not be freed.
53251662Sdim              Relinquished,
54251662Sdim              // We are no longer guaranteed to have observed all manipulations
55251662Sdim              // of this pointer/memory. For example, it could have been
56251662Sdim              // passed as a parameter to an opaque function.
57251662Sdim              Escaped
58251662Sdim  };
59249423Sdim
60218887Sdim  const Stmt *S;
61249423Sdim  unsigned K : 2; // Kind enum, but stored as a bitfield.
62249423Sdim  unsigned Family : 30; // Rest of 32-bit word, currently just an allocation
63249423Sdim                        // family.
64218887Sdim
65249423Sdim  RefState(Kind k, const Stmt *s, unsigned family)
66251662Sdim    : S(s), K(k), Family(family) {
67251662Sdim    assert(family != AF_None);
68251662Sdim  }
69218887Sdimpublic:
70239462Sdim  bool isAllocated() const { return K == Allocated; }
71218887Sdim  bool isReleased() const { return K == Released; }
72239462Sdim  bool isRelinquished() const { return K == Relinquished; }
73251662Sdim  bool isEscaped() const { return K == Escaped; }
74251662Sdim  AllocationFamily getAllocationFamily() const {
75249423Sdim    return (AllocationFamily)Family;
76249423Sdim  }
77234353Sdim  const Stmt *getStmt() const { return S; }
78234353Sdim
79218887Sdim  bool operator==(const RefState &X) const {
80249423Sdim    return K == X.K && S == X.S && Family == X.Family;
81218887Sdim  }
82218887Sdim
83249423Sdim  static RefState getAllocated(unsigned family, const Stmt *s) {
84249423Sdim    return RefState(Allocated, s, family);
85218887Sdim  }
86249423Sdim  static RefState getReleased(unsigned family, const Stmt *s) {
87249423Sdim    return RefState(Released, s, family);
88218887Sdim  }
89249423Sdim  static RefState getRelinquished(unsigned family, const Stmt *s) {
90249423Sdim    return RefState(Relinquished, s, family);
91249423Sdim  }
92251662Sdim  static RefState getEscaped(const RefState *RS) {
93251662Sdim    return RefState(Escaped, RS->getStmt(), RS->getAllocationFamily());
94251662Sdim  }
95218887Sdim
96218887Sdim  void Profile(llvm::FoldingSetNodeID &ID) const {
97218887Sdim    ID.AddInteger(K);
98218887Sdim    ID.AddPointer(S);
99249423Sdim    ID.AddInteger(Family);
100218887Sdim  }
101249423Sdim
102249423Sdim  void dump(raw_ostream &OS) const {
103263508Sdim    static const char *const Table[] = {
104249423Sdim      "Allocated",
105249423Sdim      "Released",
106249423Sdim      "Relinquished"
107249423Sdim    };
108249423Sdim    OS << Table[(unsigned) K];
109249423Sdim  }
110249423Sdim
111249423Sdim  LLVM_ATTRIBUTE_USED void dump() const {
112249423Sdim    dump(llvm::errs());
113249423Sdim  }
114218887Sdim};
115218887Sdim
116243830Sdimenum ReallocPairKind {
117243830Sdim  RPToBeFreedAfterFailure,
118243830Sdim  // The symbol has been freed when reallocation failed.
119243830Sdim  RPIsFreeOnFailure,
120243830Sdim  // The symbol does not need to be freed after reallocation fails.
121243830Sdim  RPDoNotTrackAfterFailure
122243830Sdim};
123243830Sdim
124243830Sdim/// \class ReallocPair
125243830Sdim/// \brief Stores information about the symbol being reallocated by a call to
126243830Sdim/// 'realloc' to allow modeling failed reallocation later in the path.
127234353Sdimstruct ReallocPair {
128243830Sdim  // \brief The symbol which realloc reallocated.
129234353Sdim  SymbolRef ReallocatedSym;
130243830Sdim  ReallocPairKind Kind;
131243830Sdim
132243830Sdim  ReallocPair(SymbolRef S, ReallocPairKind K) :
133243830Sdim    ReallocatedSym(S), Kind(K) {}
134234353Sdim  void Profile(llvm::FoldingSetNodeID &ID) const {
135243830Sdim    ID.AddInteger(Kind);
136234353Sdim    ID.AddPointer(ReallocatedSym);
137234353Sdim  }
138234353Sdim  bool operator==(const ReallocPair &X) const {
139234353Sdim    return ReallocatedSym == X.ReallocatedSym &&
140243830Sdim           Kind == X.Kind;
141234353Sdim  }
142234353Sdim};
143218887Sdim
144249423Sdimtypedef std::pair<const ExplodedNode*, const MemRegion*> LeakInfo;
145218887Sdim
146234353Sdimclass MallocChecker : public Checker<check::DeadSymbols,
147249423Sdim                                     check::PointerEscape,
148249423Sdim                                     check::ConstPointerEscape,
149234353Sdim                                     check::PreStmt<ReturnStmt>,
150251662Sdim                                     check::PreCall,
151234353Sdim                                     check::PostStmt<CallExpr>,
152249423Sdim                                     check::PostStmt<CXXNewExpr>,
153249423Sdim                                     check::PreStmt<CXXDeleteExpr>,
154234353Sdim                                     check::PostStmt<BlockExpr>,
155243830Sdim                                     check::PostObjCMessage,
156234353Sdim                                     check::Location,
157249423Sdim                                     eval::Assume>
158234353Sdim{
159234353Sdim  mutable OwningPtr<BugType> BT_DoubleFree;
160234353Sdim  mutable OwningPtr<BugType> BT_Leak;
161234353Sdim  mutable OwningPtr<BugType> BT_UseFree;
162234353Sdim  mutable OwningPtr<BugType> BT_BadFree;
163249423Sdim  mutable OwningPtr<BugType> BT_MismatchedDealloc;
164249423Sdim  mutable OwningPtr<BugType> BT_OffsetFree;
165234353Sdim  mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc,
166234353Sdim                         *II_valloc, *II_reallocf, *II_strndup, *II_strdup;
167234353Sdim
168218887Sdimpublic:
169234353Sdim  MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0),
170234353Sdim                    II_valloc(0), II_reallocf(0), II_strndup(0), II_strdup(0) {}
171218887Sdim
172234353Sdim  /// In pessimistic mode, the checker assumes that it does not know which
173234353Sdim  /// functions might free the memory.
174234353Sdim  struct ChecksFilter {
175234353Sdim    DefaultBool CMallocPessimistic;
176234353Sdim    DefaultBool CMallocOptimistic;
177249423Sdim    DefaultBool CNewDeleteChecker;
178251662Sdim    DefaultBool CNewDeleteLeaksChecker;
179249423Sdim    DefaultBool CMismatchedDeallocatorChecker;
180234353Sdim  };
181234353Sdim
182234353Sdim  ChecksFilter Filter;
183234353Sdim
184251662Sdim  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
185234353Sdim  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
186249423Sdim  void checkPostStmt(const CXXNewExpr *NE, CheckerContext &C) const;
187249423Sdim  void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const;
188243830Sdim  void checkPostObjCMessage(const ObjCMethodCall &Call, CheckerContext &C) const;
189234353Sdim  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
190221345Sdim  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
191221345Sdim  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
192234353Sdim  ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
193221345Sdim                            bool Assumption) const;
194226633Sdim  void checkLocation(SVal l, bool isLoad, const Stmt *S,
195226633Sdim                     CheckerContext &C) const;
196221345Sdim
197249423Sdim  ProgramStateRef checkPointerEscape(ProgramStateRef State,
198249423Sdim                                    const InvalidatedSymbols &Escaped,
199249423Sdim                                    const CallEvent *Call,
200249423Sdim                                    PointerEscapeKind Kind) const;
201249423Sdim  ProgramStateRef checkConstPointerEscape(ProgramStateRef State,
202249423Sdim                                          const InvalidatedSymbols &Escaped,
203249423Sdim                                          const CallEvent *Call,
204249423Sdim                                          PointerEscapeKind Kind) const;
205249423Sdim
206239462Sdim  void printState(raw_ostream &Out, ProgramStateRef State,
207239462Sdim                  const char *NL, const char *Sep) const;
208239462Sdim
209218887Sdimprivate:
210234353Sdim  void initIdentifierInfo(ASTContext &C) const;
211234353Sdim
212249423Sdim  /// \brief Determine family of a deallocation expression.
213249423Sdim  AllocationFamily getAllocationFamily(CheckerContext &C, const Stmt *S) const;
214249423Sdim
215249423Sdim  /// \brief Print names of allocators and deallocators.
216249423Sdim  ///
217249423Sdim  /// \returns true on success.
218249423Sdim  bool printAllocDeallocName(raw_ostream &os, CheckerContext &C,
219249423Sdim                             const Expr *E) const;
220249423Sdim
221249423Sdim  /// \brief Print expected name of an allocator based on the deallocator's
222249423Sdim  /// family derived from the DeallocExpr.
223249423Sdim  void printExpectedAllocName(raw_ostream &os, CheckerContext &C,
224249423Sdim                              const Expr *DeallocExpr) const;
225249423Sdim  /// \brief Print expected name of a deallocator based on the allocator's
226249423Sdim  /// family.
227249423Sdim  void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family) const;
228249423Sdim
229249423Sdim  ///@{
230234353Sdim  /// Check if this is one of the functions which can allocate/reallocate memory
231234353Sdim  /// pointed to by one of its arguments.
232234353Sdim  bool isMemFunction(const FunctionDecl *FD, ASTContext &C) const;
233239462Sdim  bool isFreeFunction(const FunctionDecl *FD, ASTContext &C) const;
234239462Sdim  bool isAllocationFunction(const FunctionDecl *FD, ASTContext &C) const;
235249423Sdim  bool isStandardNewDelete(const FunctionDecl *FD, ASTContext &C) const;
236249423Sdim  ///@}
237234353Sdim  static ProgramStateRef MallocMemReturnsAttr(CheckerContext &C,
238234353Sdim                                              const CallExpr *CE,
239234353Sdim                                              const OwnershipAttr* Att);
240234353Sdim  static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
241221345Sdim                                     const Expr *SizeEx, SVal Init,
242249423Sdim                                     ProgramStateRef State,
243249423Sdim                                     AllocationFamily Family = AF_Malloc) {
244234353Sdim    return MallocMemAux(C, CE,
245249423Sdim                        State->getSVal(SizeEx, C.getLocationContext()),
246249423Sdim                        Init, State, Family);
247218887Sdim  }
248234353Sdim
249234353Sdim  static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
250221345Sdim                                     SVal SizeEx, SVal Init,
251249423Sdim                                     ProgramStateRef State,
252249423Sdim                                     AllocationFamily Family = AF_Malloc);
253218887Sdim
254234353Sdim  /// Update the RefState to reflect the new memory allocation.
255249423Sdim  static ProgramStateRef
256249423Sdim  MallocUpdateRefState(CheckerContext &C, const Expr *E, ProgramStateRef State,
257249423Sdim                       AllocationFamily Family = AF_Malloc);
258218887Sdim
259234353Sdim  ProgramStateRef FreeMemAttr(CheckerContext &C, const CallExpr *CE,
260234353Sdim                              const OwnershipAttr* Att) const;
261234353Sdim  ProgramStateRef FreeMemAux(CheckerContext &C, const CallExpr *CE,
262239462Sdim                             ProgramStateRef state, unsigned Num,
263243830Sdim                             bool Hold,
264243830Sdim                             bool &ReleasedAllocated,
265243830Sdim                             bool ReturnsNullOnFailure = false) const;
266239462Sdim  ProgramStateRef FreeMemAux(CheckerContext &C, const Expr *Arg,
267239462Sdim                             const Expr *ParentExpr,
268243830Sdim                             ProgramStateRef State,
269243830Sdim                             bool Hold,
270243830Sdim                             bool &ReleasedAllocated,
271243830Sdim                             bool ReturnsNullOnFailure = false) const;
272234353Sdim
273234353Sdim  ProgramStateRef ReallocMem(CheckerContext &C, const CallExpr *CE,
274234353Sdim                             bool FreesMemOnFailure) const;
275234353Sdim  static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE);
276218887Sdim
277239462Sdim  ///\brief Check if the memory associated with this symbol was released.
278239462Sdim  bool isReleased(SymbolRef Sym, CheckerContext &C) const;
279239462Sdim
280249423Sdim  bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const;
281234353Sdim
282263508Sdim  /// Check if the function is known free memory, or if it is
283249423Sdim  /// "interesting" and should be modeled explicitly.
284249423Sdim  ///
285263508Sdim  /// \param [out] EscapingSymbol A function might not free memory in general,
286263508Sdim  ///   but could be known to free a particular symbol. In this case, false is
287263508Sdim  ///   returned and the single escaping symbol is returned through the out
288263508Sdim  ///   parameter.
289263508Sdim  ///
290249423Sdim  /// We assume that pointers do not escape through calls to system functions
291249423Sdim  /// not handled by this checker.
292263508Sdim  bool mayFreeAnyEscapedMemoryOrIsModeledExplicitly(const CallEvent *Call,
293263508Sdim                                   ProgramStateRef State,
294263508Sdim                                   SymbolRef &EscapingSymbol) const;
295234353Sdim
296249423Sdim  // Implementation of the checkPointerEscape callabcks.
297249423Sdim  ProgramStateRef checkPointerEscapeAux(ProgramStateRef State,
298249423Sdim                                  const InvalidatedSymbols &Escaped,
299249423Sdim                                  const CallEvent *Call,
300249423Sdim                                  PointerEscapeKind Kind,
301249423Sdim                                  bool(*CheckRefState)(const RefState*)) const;
302249423Sdim
303251662Sdim  ///@{
304251662Sdim  /// Tells if a given family/call/symbol is tracked by the current checker.
305251662Sdim  bool isTrackedByCurrentChecker(AllocationFamily Family) const;
306251662Sdim  bool isTrackedByCurrentChecker(CheckerContext &C,
307251662Sdim                                 const Stmt *AllocDeallocStmt) const;
308251662Sdim  bool isTrackedByCurrentChecker(CheckerContext &C, SymbolRef Sym) const;
309251662Sdim  ///@}
310226633Sdim  static bool SummarizeValue(raw_ostream &os, SVal V);
311226633Sdim  static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
312249423Sdim  void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
313249423Sdim                     const Expr *DeallocExpr) const;
314249423Sdim  void ReportMismatchedDealloc(CheckerContext &C, SourceRange Range,
315251662Sdim                               const Expr *DeallocExpr, const RefState *RS,
316263508Sdim                               SymbolRef Sym, bool OwnershipTransferred) const;
317249423Sdim  void ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range,
318249423Sdim                        const Expr *DeallocExpr,
319249423Sdim                        const Expr *AllocExpr = 0) const;
320249423Sdim  void ReportUseAfterFree(CheckerContext &C, SourceRange Range,
321249423Sdim                          SymbolRef Sym) const;
322249423Sdim  void ReportDoubleFree(CheckerContext &C, SourceRange Range, bool Released,
323249423Sdim                        SymbolRef Sym, SymbolRef PrevSym) const;
324234353Sdim
325234353Sdim  /// Find the location of the allocation for Sym on the path leading to the
326234353Sdim  /// exploded node N.
327234353Sdim  LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
328234353Sdim                             CheckerContext &C) const;
329234353Sdim
330234353Sdim  void reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const;
331234353Sdim
332234353Sdim  /// The bug visitor which allows us to print extra diagnostics along the
333234353Sdim  /// BugReport path. For example, showing the allocation site of the leaked
334234353Sdim  /// region.
335234353Sdim  class MallocBugVisitor : public BugReporterVisitorImpl<MallocBugVisitor> {
336234353Sdim  protected:
337234353Sdim    enum NotificationMode {
338234353Sdim      Normal,
339234353Sdim      ReallocationFailed
340234353Sdim    };
341234353Sdim
342234353Sdim    // The allocated region symbol tracked by the main analysis.
343234353Sdim    SymbolRef Sym;
344234353Sdim
345239462Sdim    // The mode we are in, i.e. what kind of diagnostics will be emitted.
346239462Sdim    NotificationMode Mode;
347234353Sdim
348239462Sdim    // A symbol from when the primary region should have been reallocated.
349239462Sdim    SymbolRef FailedReallocSymbol;
350234353Sdim
351239462Sdim    bool IsLeak;
352234353Sdim
353239462Sdim  public:
354239462Sdim    MallocBugVisitor(SymbolRef S, bool isLeak = false)
355239462Sdim       : Sym(S), Mode(Normal), FailedReallocSymbol(0), IsLeak(isLeak) {}
356239462Sdim
357234353Sdim    virtual ~MallocBugVisitor() {}
358234353Sdim
359234353Sdim    void Profile(llvm::FoldingSetNodeID &ID) const {
360234353Sdim      static int X = 0;
361234353Sdim      ID.AddPointer(&X);
362234353Sdim      ID.AddPointer(Sym);
363234353Sdim    }
364234353Sdim
365234353Sdim    inline bool isAllocated(const RefState *S, const RefState *SPrev,
366234353Sdim                            const Stmt *Stmt) {
367234353Sdim      // Did not track -> allocated. Other state (released) -> allocated.
368249423Sdim      return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXNewExpr>(Stmt)) &&
369234353Sdim              (S && S->isAllocated()) && (!SPrev || !SPrev->isAllocated()));
370234353Sdim    }
371234353Sdim
372234353Sdim    inline bool isReleased(const RefState *S, const RefState *SPrev,
373234353Sdim                           const Stmt *Stmt) {
374234353Sdim      // Did not track -> released. Other state (allocated) -> released.
375249423Sdim      return (Stmt && (isa<CallExpr>(Stmt) || isa<CXXDeleteExpr>(Stmt)) &&
376234353Sdim              (S && S->isReleased()) && (!SPrev || !SPrev->isReleased()));
377234353Sdim    }
378234353Sdim
379239462Sdim    inline bool isRelinquished(const RefState *S, const RefState *SPrev,
380239462Sdim                               const Stmt *Stmt) {
381239462Sdim      // Did not track -> relinquished. Other state (allocated) -> relinquished.
382239462Sdim      return (Stmt && (isa<CallExpr>(Stmt) || isa<ObjCMessageExpr>(Stmt) ||
383239462Sdim                                              isa<ObjCPropertyRefExpr>(Stmt)) &&
384239462Sdim              (S && S->isRelinquished()) &&
385239462Sdim              (!SPrev || !SPrev->isRelinquished()));
386239462Sdim    }
387239462Sdim
388234353Sdim    inline bool isReallocFailedCheck(const RefState *S, const RefState *SPrev,
389234353Sdim                                     const Stmt *Stmt) {
390234353Sdim      // If the expression is not a call, and the state change is
391234353Sdim      // released -> allocated, it must be the realloc return value
392234353Sdim      // check. If we have to handle more cases here, it might be cleaner just
393234353Sdim      // to track this extra bit in the state itself.
394234353Sdim      return ((!Stmt || !isa<CallExpr>(Stmt)) &&
395234353Sdim              (S && S->isAllocated()) && (SPrev && !SPrev->isAllocated()));
396234353Sdim    }
397234353Sdim
398234353Sdim    PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
399234353Sdim                                   const ExplodedNode *PrevN,
400234353Sdim                                   BugReporterContext &BRC,
401234353Sdim                                   BugReport &BR);
402239462Sdim
403239462Sdim    PathDiagnosticPiece* getEndPath(BugReporterContext &BRC,
404239462Sdim                                    const ExplodedNode *EndPathNode,
405239462Sdim                                    BugReport &BR) {
406239462Sdim      if (!IsLeak)
407239462Sdim        return 0;
408239462Sdim
409239462Sdim      PathDiagnosticLocation L =
410239462Sdim        PathDiagnosticLocation::createEndOfPath(EndPathNode,
411239462Sdim                                                BRC.getSourceManager());
412239462Sdim      // Do not add the statement itself as a range in case of leak.
413239462Sdim      return new PathDiagnosticEventPiece(L, BR.getDescription(), false);
414239462Sdim    }
415239462Sdim
416234353Sdim  private:
417234353Sdim    class StackHintGeneratorForReallocationFailed
418234353Sdim        : public StackHintGeneratorForSymbol {
419234353Sdim    public:
420234353Sdim      StackHintGeneratorForReallocationFailed(SymbolRef S, StringRef M)
421234353Sdim        : StackHintGeneratorForSymbol(S, M) {}
422234353Sdim
423234353Sdim      virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex) {
424243830Sdim        // Printed parameters start at 1, not 0.
425243830Sdim        ++ArgIndex;
426243830Sdim
427234353Sdim        SmallString<200> buf;
428234353Sdim        llvm::raw_svector_ostream os(buf);
429234353Sdim
430243830Sdim        os << "Reallocation of " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
431243830Sdim           << " parameter failed";
432234353Sdim
433234353Sdim        return os.str();
434234353Sdim      }
435234353Sdim
436234353Sdim      virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
437234353Sdim        return "Reallocation of returned value failed";
438234353Sdim      }
439234353Sdim    };
440234353Sdim  };
441218887Sdim};
442218887Sdim} // end anonymous namespace
443218887Sdim
444243830SdimREGISTER_MAP_WITH_PROGRAMSTATE(RegionState, SymbolRef, RefState)
445243830SdimREGISTER_MAP_WITH_PROGRAMSTATE(ReallocPairs, SymbolRef, ReallocPair)
446234353Sdim
447243830Sdim// A map from the freed symbol to the symbol representing the return value of
448243830Sdim// the free function.
449243830SdimREGISTER_MAP_WITH_PROGRAMSTATE(FreeReturnValue, SymbolRef, SymbolRef)
450218887Sdim
451234353Sdimnamespace {
452234353Sdimclass StopTrackingCallback : public SymbolVisitor {
453234353Sdim  ProgramStateRef state;
454234353Sdimpublic:
455234353Sdim  StopTrackingCallback(ProgramStateRef st) : state(st) {}
456234353Sdim  ProgramStateRef getState() const { return state; }
457218887Sdim
458234353Sdim  bool VisitSymbol(SymbolRef sym) {
459234353Sdim    state = state->remove<RegionState>(sym);
460234353Sdim    return true;
461234353Sdim  }
462234353Sdim};
463234353Sdim} // end anonymous namespace
464218887Sdim
465234353Sdimvoid MallocChecker::initIdentifierInfo(ASTContext &Ctx) const {
466239462Sdim  if (II_malloc)
467239462Sdim    return;
468239462Sdim  II_malloc = &Ctx.Idents.get("malloc");
469239462Sdim  II_free = &Ctx.Idents.get("free");
470239462Sdim  II_realloc = &Ctx.Idents.get("realloc");
471239462Sdim  II_reallocf = &Ctx.Idents.get("reallocf");
472239462Sdim  II_calloc = &Ctx.Idents.get("calloc");
473239462Sdim  II_valloc = &Ctx.Idents.get("valloc");
474239462Sdim  II_strdup = &Ctx.Idents.get("strdup");
475239462Sdim  II_strndup = &Ctx.Idents.get("strndup");
476234353Sdim}
477218887Sdim
478234353Sdimbool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {
479239462Sdim  if (isFreeFunction(FD, C))
480239462Sdim    return true;
481239462Sdim
482239462Sdim  if (isAllocationFunction(FD, C))
483239462Sdim    return true;
484239462Sdim
485249423Sdim  if (isStandardNewDelete(FD, C))
486249423Sdim    return true;
487249423Sdim
488239462Sdim  return false;
489239462Sdim}
490239462Sdim
491239462Sdimbool MallocChecker::isAllocationFunction(const FunctionDecl *FD,
492239462Sdim                                         ASTContext &C) const {
493234353Sdim  if (!FD)
494234353Sdim    return false;
495218887Sdim
496239462Sdim  if (FD->getKind() == Decl::Function) {
497239462Sdim    IdentifierInfo *FunI = FD->getIdentifier();
498239462Sdim    initIdentifierInfo(C);
499218887Sdim
500239462Sdim    if (FunI == II_malloc || FunI == II_realloc ||
501239462Sdim        FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc ||
502239462Sdim        FunI == II_strdup || FunI == II_strndup)
503239462Sdim      return true;
504239462Sdim  }
505218887Sdim
506239462Sdim  if (Filter.CMallocOptimistic && FD->hasAttrs())
507239462Sdim    for (specific_attr_iterator<OwnershipAttr>
508239462Sdim           i = FD->specific_attr_begin<OwnershipAttr>(),
509239462Sdim           e = FD->specific_attr_end<OwnershipAttr>();
510239462Sdim           i != e; ++i)
511239462Sdim      if ((*i)->getOwnKind() == OwnershipAttr::Returns)
512239462Sdim        return true;
513239462Sdim  return false;
514239462Sdim}
515218887Sdim
516239462Sdimbool MallocChecker::isFreeFunction(const FunctionDecl *FD, ASTContext &C) const {
517239462Sdim  if (!FD)
518239462Sdim    return false;
519234353Sdim
520239462Sdim  if (FD->getKind() == Decl::Function) {
521239462Sdim    IdentifierInfo *FunI = FD->getIdentifier();
522239462Sdim    initIdentifierInfo(C);
523239462Sdim
524239462Sdim    if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf)
525239462Sdim      return true;
526239462Sdim  }
527239462Sdim
528239462Sdim  if (Filter.CMallocOptimistic && FD->hasAttrs())
529239462Sdim    for (specific_attr_iterator<OwnershipAttr>
530239462Sdim           i = FD->specific_attr_begin<OwnershipAttr>(),
531239462Sdim           e = FD->specific_attr_end<OwnershipAttr>();
532239462Sdim           i != e; ++i)
533239462Sdim      if ((*i)->getOwnKind() == OwnershipAttr::Takes ||
534239462Sdim          (*i)->getOwnKind() == OwnershipAttr::Holds)
535239462Sdim        return true;
536234353Sdim  return false;
537234353Sdim}
538234353Sdim
539249423Sdim// Tells if the callee is one of the following:
540249423Sdim// 1) A global non-placement new/delete operator function.
541249423Sdim// 2) A global placement operator function with the single placement argument
542249423Sdim//    of type std::nothrow_t.
543249423Sdimbool MallocChecker::isStandardNewDelete(const FunctionDecl *FD,
544249423Sdim                                        ASTContext &C) const {
545249423Sdim  if (!FD)
546249423Sdim    return false;
547249423Sdim
548249423Sdim  OverloadedOperatorKind Kind = FD->getOverloadedOperator();
549249423Sdim  if (Kind != OO_New && Kind != OO_Array_New &&
550249423Sdim      Kind != OO_Delete && Kind != OO_Array_Delete)
551249423Sdim    return false;
552249423Sdim
553249423Sdim  // Skip all operator new/delete methods.
554249423Sdim  if (isa<CXXMethodDecl>(FD))
555249423Sdim    return false;
556249423Sdim
557249423Sdim  // Return true if tested operator is a standard placement nothrow operator.
558249423Sdim  if (FD->getNumParams() == 2) {
559249423Sdim    QualType T = FD->getParamDecl(1)->getType();
560249423Sdim    if (const IdentifierInfo *II = T.getBaseTypeIdentifier())
561249423Sdim      return II->getName().equals("nothrow_t");
562249423Sdim  }
563249423Sdim
564249423Sdim  // Skip placement operators.
565249423Sdim  if (FD->getNumParams() != 1 || FD->isVariadic())
566249423Sdim    return false;
567249423Sdim
568249423Sdim  // One of the standard new/new[]/delete/delete[] non-placement operators.
569249423Sdim  return true;
570249423Sdim}
571249423Sdim
572234353Sdimvoid MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
573243830Sdim  if (C.wasInlined)
574243830Sdim    return;
575243830Sdim
576234353Sdim  const FunctionDecl *FD = C.getCalleeDecl(CE);
577234353Sdim  if (!FD)
578234353Sdim    return;
579234353Sdim
580239462Sdim  ProgramStateRef State = C.getState();
581243830Sdim  bool ReleasedAllocatedMemory = false;
582234353Sdim
583239462Sdim  if (FD->getKind() == Decl::Function) {
584239462Sdim    initIdentifierInfo(C.getASTContext());
585239462Sdim    IdentifierInfo *FunI = FD->getIdentifier();
586239462Sdim
587239462Sdim    if (FunI == II_malloc || FunI == II_valloc) {
588239462Sdim      if (CE->getNumArgs() < 1)
589239462Sdim        return;
590239462Sdim      State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
591239462Sdim    } else if (FunI == II_realloc) {
592239462Sdim      State = ReallocMem(C, CE, false);
593239462Sdim    } else if (FunI == II_reallocf) {
594239462Sdim      State = ReallocMem(C, CE, true);
595239462Sdim    } else if (FunI == II_calloc) {
596239462Sdim      State = CallocMem(C, CE);
597239462Sdim    } else if (FunI == II_free) {
598243830Sdim      State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
599239462Sdim    } else if (FunI == II_strdup) {
600239462Sdim      State = MallocUpdateRefState(C, CE, State);
601239462Sdim    } else if (FunI == II_strndup) {
602239462Sdim      State = MallocUpdateRefState(C, CE, State);
603239462Sdim    }
604249423Sdim    else if (isStandardNewDelete(FD, C.getASTContext())) {
605249423Sdim      // Process direct calls to operator new/new[]/delete/delete[] functions
606249423Sdim      // as distinct from new/new[]/delete/delete[] expressions that are
607249423Sdim      // processed by the checkPostStmt callbacks for CXXNewExpr and
608249423Sdim      // CXXDeleteExpr.
609249423Sdim      OverloadedOperatorKind K = FD->getOverloadedOperator();
610249423Sdim      if (K == OO_New)
611249423Sdim        State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
612249423Sdim                             AF_CXXNew);
613249423Sdim      else if (K == OO_Array_New)
614249423Sdim        State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
615249423Sdim                             AF_CXXNewArray);
616249423Sdim      else if (K == OO_Delete || K == OO_Array_Delete)
617249423Sdim        State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
618249423Sdim      else
619249423Sdim        llvm_unreachable("not a new/delete operator");
620249423Sdim    }
621239462Sdim  }
622239462Sdim
623249423Sdim  if (Filter.CMallocOptimistic || Filter.CMismatchedDeallocatorChecker) {
624234353Sdim    // Check all the attributes, if there are any.
625234353Sdim    // There can be multiple of these attributes.
626234353Sdim    if (FD->hasAttrs())
627234353Sdim      for (specific_attr_iterator<OwnershipAttr>
628234353Sdim          i = FD->specific_attr_begin<OwnershipAttr>(),
629234353Sdim          e = FD->specific_attr_end<OwnershipAttr>();
630234353Sdim          i != e; ++i) {
631234353Sdim        switch ((*i)->getOwnKind()) {
632234353Sdim        case OwnershipAttr::Returns:
633234353Sdim          State = MallocMemReturnsAttr(C, CE, *i);
634234353Sdim          break;
635234353Sdim        case OwnershipAttr::Takes:
636234353Sdim        case OwnershipAttr::Holds:
637234353Sdim          State = FreeMemAttr(C, CE, *i);
638234353Sdim          break;
639234353Sdim        }
640218887Sdim      }
641218887Sdim  }
642234353Sdim  C.addTransition(State);
643218887Sdim}
644218887Sdim
645249423Sdimvoid MallocChecker::checkPostStmt(const CXXNewExpr *NE,
646249423Sdim                                  CheckerContext &C) const {
647249423Sdim
648249423Sdim  if (NE->getNumPlacementArgs())
649249423Sdim    for (CXXNewExpr::const_arg_iterator I = NE->placement_arg_begin(),
650249423Sdim         E = NE->placement_arg_end(); I != E; ++I)
651249423Sdim      if (SymbolRef Sym = C.getSVal(*I).getAsSymbol())
652249423Sdim        checkUseAfterFree(Sym, C, *I);
653249423Sdim
654249423Sdim  if (!isStandardNewDelete(NE->getOperatorNew(), C.getASTContext()))
655249423Sdim    return;
656249423Sdim
657249423Sdim  ProgramStateRef State = C.getState();
658249423Sdim  // The return value from operator new is bound to a specified initialization
659249423Sdim  // value (if any) and we don't want to loose this value. So we call
660249423Sdim  // MallocUpdateRefState() instead of MallocMemAux() which breakes the
661249423Sdim  // existing binding.
662249423Sdim  State = MallocUpdateRefState(C, NE, State, NE->isArray() ? AF_CXXNewArray
663249423Sdim                                                           : AF_CXXNew);
664249423Sdim  C.addTransition(State);
665249423Sdim}
666249423Sdim
667249423Sdimvoid MallocChecker::checkPreStmt(const CXXDeleteExpr *DE,
668249423Sdim                                 CheckerContext &C) const {
669249423Sdim
670249423Sdim  if (!Filter.CNewDeleteChecker)
671249423Sdim    if (SymbolRef Sym = C.getSVal(DE->getArgument()).getAsSymbol())
672249423Sdim      checkUseAfterFree(Sym, C, DE->getArgument());
673249423Sdim
674249423Sdim  if (!isStandardNewDelete(DE->getOperatorDelete(), C.getASTContext()))
675249423Sdim    return;
676249423Sdim
677249423Sdim  ProgramStateRef State = C.getState();
678249423Sdim  bool ReleasedAllocated;
679249423Sdim  State = FreeMemAux(C, DE->getArgument(), DE, State,
680249423Sdim                     /*Hold*/false, ReleasedAllocated);
681249423Sdim
682249423Sdim  C.addTransition(State);
683249423Sdim}
684249423Sdim
685249423Sdimstatic bool isKnownDeallocObjCMethodName(const ObjCMethodCall &Call) {
686249423Sdim  // If the first selector piece is one of the names below, assume that the
687249423Sdim  // object takes ownership of the memory, promising to eventually deallocate it
688249423Sdim  // with free().
689249423Sdim  // Ex:  [NSData dataWithBytesNoCopy:bytes length:10];
690249423Sdim  // (...unless a 'freeWhenDone' parameter is false, but that's checked later.)
691249423Sdim  StringRef FirstSlot = Call.getSelector().getNameForSlot(0);
692249423Sdim  if (FirstSlot == "dataWithBytesNoCopy" ||
693249423Sdim      FirstSlot == "initWithBytesNoCopy" ||
694249423Sdim      FirstSlot == "initWithCharactersNoCopy")
695249423Sdim    return true;
696249423Sdim
697249423Sdim  return false;
698249423Sdim}
699249423Sdim
700249423Sdimstatic Optional<bool> getFreeWhenDoneArg(const ObjCMethodCall &Call) {
701239462Sdim  Selector S = Call.getSelector();
702249423Sdim
703249423Sdim  // FIXME: We should not rely on fully-constrained symbols being folded.
704239462Sdim  for (unsigned i = 1; i < S.getNumArgs(); ++i)
705239462Sdim    if (S.getNameForSlot(i).equals("freeWhenDone"))
706249423Sdim      return !Call.getArgSVal(i).isZeroConstant();
707239462Sdim
708249423Sdim  return None;
709239462Sdim}
710239462Sdim
711243830Sdimvoid MallocChecker::checkPostObjCMessage(const ObjCMethodCall &Call,
712243830Sdim                                         CheckerContext &C) const {
713249423Sdim  if (C.wasInlined)
714249423Sdim    return;
715243830Sdim
716249423Sdim  if (!isKnownDeallocObjCMethodName(Call))
717249423Sdim    return;
718249423Sdim
719249423Sdim  if (Optional<bool> FreeWhenDone = getFreeWhenDoneArg(Call))
720249423Sdim    if (!*FreeWhenDone)
721249423Sdim      return;
722249423Sdim
723249423Sdim  bool ReleasedAllocatedMemory;
724249423Sdim  ProgramStateRef State = FreeMemAux(C, Call.getArgExpr(0),
725249423Sdim                                     Call.getOriginExpr(), C.getState(),
726249423Sdim                                     /*Hold=*/true, ReleasedAllocatedMemory,
727249423Sdim                                     /*RetNullOnFailure=*/true);
728249423Sdim
729249423Sdim  C.addTransition(State);
730239462Sdim}
731239462Sdim
732234353SdimProgramStateRef MallocChecker::MallocMemReturnsAttr(CheckerContext &C,
733234353Sdim                                                    const CallExpr *CE,
734234353Sdim                                                    const OwnershipAttr* Att) {
735218887Sdim  if (Att->getModule() != "malloc")
736234353Sdim    return 0;
737218887Sdim
738218887Sdim  OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
739218887Sdim  if (I != E) {
740234353Sdim    return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
741218887Sdim  }
742234353Sdim  return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), C.getState());
743218887Sdim}
744218887Sdim
745234353SdimProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
746218887Sdim                                           const CallExpr *CE,
747218887Sdim                                           SVal Size, SVal Init,
748249423Sdim                                           ProgramStateRef State,
749249423Sdim                                           AllocationFamily Family) {
750218887Sdim
751239462Sdim  // Bind the return value to the symbolic value from the heap region.
752239462Sdim  // TODO: We could rewrite post visit to eval call; 'malloc' does not have
753239462Sdim  // side effects other than what we model here.
754243830Sdim  unsigned Count = C.blockCount();
755239462Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
756239462Sdim  const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
757249423Sdim  DefinedSVal RetVal = svalBuilder.getConjuredHeapSymbolVal(CE, LCtx, Count)
758249423Sdim      .castAs<DefinedSVal>();
759249423Sdim  State = State->BindExpr(CE, C.getLocationContext(), RetVal);
760239462Sdim
761234353Sdim  // We expect the malloc functions to return a pointer.
762249423Sdim  if (!RetVal.getAs<Loc>())
763234353Sdim    return 0;
764218887Sdim
765218887Sdim  // Fill the region with the initialization value.
766249423Sdim  State = State->bindDefault(RetVal, Init);
767218887Sdim
768218887Sdim  // Set the region's extent equal to the Size parameter.
769234353Sdim  const SymbolicRegion *R =
770239462Sdim      dyn_cast_or_null<SymbolicRegion>(RetVal.getAsRegion());
771234353Sdim  if (!R)
772234353Sdim    return 0;
773249423Sdim  if (Optional<DefinedOrUnknownSVal> DefinedSize =
774249423Sdim          Size.getAs<DefinedOrUnknownSVal>()) {
775234353Sdim    SValBuilder &svalBuilder = C.getSValBuilder();
776234353Sdim    DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
777234353Sdim    DefinedOrUnknownSVal extentMatchesSize =
778249423Sdim        svalBuilder.evalEQ(State, Extent, *DefinedSize);
779218887Sdim
780249423Sdim    State = State->assume(extentMatchesSize, true);
781249423Sdim    assert(State);
782234353Sdim  }
783218887Sdim
784249423Sdim  return MallocUpdateRefState(C, CE, State, Family);
785234353Sdim}
786234353Sdim
787234353SdimProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C,
788249423Sdim                                                    const Expr *E,
789249423Sdim                                                    ProgramStateRef State,
790249423Sdim                                                    AllocationFamily Family) {
791234353Sdim  // Get the return value.
792249423Sdim  SVal retVal = State->getSVal(E, C.getLocationContext());
793234353Sdim
794234353Sdim  // We expect the malloc functions to return a pointer.
795249423Sdim  if (!retVal.getAs<Loc>())
796234353Sdim    return 0;
797234353Sdim
798218887Sdim  SymbolRef Sym = retVal.getAsLocSymbol();
799218887Sdim  assert(Sym);
800218887Sdim
801218887Sdim  // Set the symbol's state to Allocated.
802249423Sdim  return State->set<RegionState>(Sym, RefState::getAllocated(Family, E));
803218887Sdim}
804218887Sdim
805234353SdimProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
806234353Sdim                                           const CallExpr *CE,
807234353Sdim                                           const OwnershipAttr* Att) const {
808218887Sdim  if (Att->getModule() != "malloc")
809234353Sdim    return 0;
810218887Sdim
811234353Sdim  ProgramStateRef State = C.getState();
812243830Sdim  bool ReleasedAllocated = false;
813234353Sdim
814218887Sdim  for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
815218887Sdim       I != E; ++I) {
816234353Sdim    ProgramStateRef StateI = FreeMemAux(C, CE, State, *I,
817243830Sdim                               Att->getOwnKind() == OwnershipAttr::Holds,
818243830Sdim                               ReleasedAllocated);
819234353Sdim    if (StateI)
820234353Sdim      State = StateI;
821218887Sdim  }
822234353Sdim  return State;
823218887Sdim}
824218887Sdim
825234353SdimProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
826234353Sdim                                          const CallExpr *CE,
827234353Sdim                                          ProgramStateRef state,
828234353Sdim                                          unsigned Num,
829243830Sdim                                          bool Hold,
830243830Sdim                                          bool &ReleasedAllocated,
831243830Sdim                                          bool ReturnsNullOnFailure) const {
832234353Sdim  if (CE->getNumArgs() < (Num + 1))
833234353Sdim    return 0;
834234353Sdim
835243830Sdim  return FreeMemAux(C, CE->getArg(Num), CE, state, Hold,
836243830Sdim                    ReleasedAllocated, ReturnsNullOnFailure);
837239462Sdim}
838239462Sdim
839243830Sdim/// Checks if the previous call to free on the given symbol failed - if free
840243830Sdim/// failed, returns true. Also, returns the corresponding return value symbol.
841249423Sdimstatic bool didPreviousFreeFail(ProgramStateRef State,
842249423Sdim                                SymbolRef Sym, SymbolRef &RetStatusSymbol) {
843243830Sdim  const SymbolRef *Ret = State->get<FreeReturnValue>(Sym);
844243830Sdim  if (Ret) {
845243830Sdim    assert(*Ret && "We should not store the null return symbol");
846243830Sdim    ConstraintManager &CMgr = State->getConstraintManager();
847243830Sdim    ConditionTruthVal FreeFailed = CMgr.isNull(State, *Ret);
848243830Sdim    RetStatusSymbol = *Ret;
849243830Sdim    return FreeFailed.isConstrainedTrue();
850243830Sdim  }
851243830Sdim  return false;
852243830Sdim}
853243830Sdim
854249423SdimAllocationFamily MallocChecker::getAllocationFamily(CheckerContext &C,
855249423Sdim                                                    const Stmt *S) const {
856249423Sdim  if (!S)
857249423Sdim    return AF_None;
858249423Sdim
859249423Sdim  if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
860249423Sdim    const FunctionDecl *FD = C.getCalleeDecl(CE);
861249423Sdim
862249423Sdim    if (!FD)
863249423Sdim      FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
864249423Sdim
865249423Sdim    ASTContext &Ctx = C.getASTContext();
866249423Sdim
867249423Sdim    if (isAllocationFunction(FD, Ctx) || isFreeFunction(FD, Ctx))
868249423Sdim      return AF_Malloc;
869249423Sdim
870249423Sdim    if (isStandardNewDelete(FD, Ctx)) {
871249423Sdim      OverloadedOperatorKind Kind = FD->getOverloadedOperator();
872249423Sdim      if (Kind == OO_New || Kind == OO_Delete)
873249423Sdim        return AF_CXXNew;
874249423Sdim      else if (Kind == OO_Array_New || Kind == OO_Array_Delete)
875249423Sdim        return AF_CXXNewArray;
876249423Sdim    }
877249423Sdim
878249423Sdim    return AF_None;
879249423Sdim  }
880249423Sdim
881249423Sdim  if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(S))
882249423Sdim    return NE->isArray() ? AF_CXXNewArray : AF_CXXNew;
883249423Sdim
884249423Sdim  if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(S))
885249423Sdim    return DE->isArrayForm() ? AF_CXXNewArray : AF_CXXNew;
886249423Sdim
887249423Sdim  if (isa<ObjCMessageExpr>(S))
888249423Sdim    return AF_Malloc;
889249423Sdim
890249423Sdim  return AF_None;
891249423Sdim}
892249423Sdim
893249423Sdimbool MallocChecker::printAllocDeallocName(raw_ostream &os, CheckerContext &C,
894249423Sdim                                          const Expr *E) const {
895249423Sdim  if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
896249423Sdim    // FIXME: This doesn't handle indirect calls.
897249423Sdim    const FunctionDecl *FD = CE->getDirectCallee();
898249423Sdim    if (!FD)
899249423Sdim      return false;
900249423Sdim
901249423Sdim    os << *FD;
902249423Sdim    if (!FD->isOverloadedOperator())
903249423Sdim      os << "()";
904249423Sdim    return true;
905249423Sdim  }
906249423Sdim
907249423Sdim  if (const ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) {
908249423Sdim    if (Msg->isInstanceMessage())
909249423Sdim      os << "-";
910249423Sdim    else
911249423Sdim      os << "+";
912249423Sdim    os << Msg->getSelector().getAsString();
913249423Sdim    return true;
914249423Sdim  }
915249423Sdim
916249423Sdim  if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(E)) {
917249423Sdim    os << "'"
918249423Sdim       << getOperatorSpelling(NE->getOperatorNew()->getOverloadedOperator())
919249423Sdim       << "'";
920249423Sdim    return true;
921249423Sdim  }
922249423Sdim
923249423Sdim  if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(E)) {
924249423Sdim    os << "'"
925249423Sdim       << getOperatorSpelling(DE->getOperatorDelete()->getOverloadedOperator())
926249423Sdim       << "'";
927249423Sdim    return true;
928249423Sdim  }
929249423Sdim
930249423Sdim  return false;
931249423Sdim}
932249423Sdim
933249423Sdimvoid MallocChecker::printExpectedAllocName(raw_ostream &os, CheckerContext &C,
934249423Sdim                                           const Expr *E) const {
935249423Sdim  AllocationFamily Family = getAllocationFamily(C, E);
936249423Sdim
937249423Sdim  switch(Family) {
938249423Sdim    case AF_Malloc: os << "malloc()"; return;
939249423Sdim    case AF_CXXNew: os << "'new'"; return;
940249423Sdim    case AF_CXXNewArray: os << "'new[]'"; return;
941249423Sdim    case AF_None: llvm_unreachable("not a deallocation expression");
942249423Sdim  }
943249423Sdim}
944249423Sdim
945249423Sdimvoid MallocChecker::printExpectedDeallocName(raw_ostream &os,
946249423Sdim                                             AllocationFamily Family) const {
947249423Sdim  switch(Family) {
948249423Sdim    case AF_Malloc: os << "free()"; return;
949249423Sdim    case AF_CXXNew: os << "'delete'"; return;
950249423Sdim    case AF_CXXNewArray: os << "'delete[]'"; return;
951249423Sdim    case AF_None: llvm_unreachable("suspicious AF_None argument");
952249423Sdim  }
953249423Sdim}
954249423Sdim
955239462SdimProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
956239462Sdim                                          const Expr *ArgExpr,
957239462Sdim                                          const Expr *ParentExpr,
958243830Sdim                                          ProgramStateRef State,
959243830Sdim                                          bool Hold,
960243830Sdim                                          bool &ReleasedAllocated,
961243830Sdim                                          bool ReturnsNullOnFailure) const {
962239462Sdim
963243830Sdim  SVal ArgVal = State->getSVal(ArgExpr, C.getLocationContext());
964249423Sdim  if (!ArgVal.getAs<DefinedOrUnknownSVal>())
965234353Sdim    return 0;
966249423Sdim  DefinedOrUnknownSVal location = ArgVal.castAs<DefinedOrUnknownSVal>();
967218887Sdim
968218887Sdim  // Check for null dereferences.
969249423Sdim  if (!location.getAs<Loc>())
970234353Sdim    return 0;
971218887Sdim
972234353Sdim  // The explicit NULL case, no operation is performed.
973234353Sdim  ProgramStateRef notNullState, nullState;
974243830Sdim  llvm::tie(notNullState, nullState) = State->assume(location);
975218887Sdim  if (nullState && !notNullState)
976234353Sdim    return 0;
977218887Sdim
978218887Sdim  // Unknown values could easily be okay
979218887Sdim  // Undefined values are handled elsewhere
980218887Sdim  if (ArgVal.isUnknownOrUndef())
981234353Sdim    return 0;
982218887Sdim
983218887Sdim  const MemRegion *R = ArgVal.getAsRegion();
984218887Sdim
985218887Sdim  // Nonlocs can't be freed, of course.
986218887Sdim  // Non-region locations (labels and fixed addresses) also shouldn't be freed.
987218887Sdim  if (!R) {
988249423Sdim    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
989234353Sdim    return 0;
990218887Sdim  }
991218887Sdim
992218887Sdim  R = R->StripCasts();
993218887Sdim
994218887Sdim  // Blocks might show up as heap data, but should not be free()d
995218887Sdim  if (isa<BlockDataRegion>(R)) {
996249423Sdim    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
997234353Sdim    return 0;
998218887Sdim  }
999218887Sdim
1000218887Sdim  const MemSpaceRegion *MS = R->getMemorySpace();
1001218887Sdim
1002249423Sdim  // Parameters, locals, statics, globals, and memory returned by alloca()
1003249423Sdim  // shouldn't be freed.
1004218887Sdim  if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
1005218887Sdim    // FIXME: at the time this code was written, malloc() regions were
1006218887Sdim    // represented by conjured symbols, which are all in UnknownSpaceRegion.
1007218887Sdim    // This means that there isn't actually anything from HeapSpaceRegion
1008218887Sdim    // that should be freed, even though we allow it here.
1009218887Sdim    // Of course, free() can work on memory allocated outside the current
1010218887Sdim    // function, so UnknownSpaceRegion is always a possibility.
1011218887Sdim    // False negatives are better than false positives.
1012218887Sdim
1013249423Sdim    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
1014234353Sdim    return 0;
1015218887Sdim  }
1016249423Sdim
1017249423Sdim  const SymbolicRegion *SrBase = dyn_cast<SymbolicRegion>(R->getBaseRegion());
1018218887Sdim  // Various cases could lead to non-symbol values here.
1019218887Sdim  // For now, ignore them.
1020249423Sdim  if (!SrBase)
1021234353Sdim    return 0;
1022218887Sdim
1023249423Sdim  SymbolRef SymBase = SrBase->getSymbol();
1024249423Sdim  const RefState *RsBase = State->get<RegionState>(SymBase);
1025243830Sdim  SymbolRef PreviousRetStatusSymbol = 0;
1026218887Sdim
1027249423Sdim  if (RsBase) {
1028243830Sdim
1029251662Sdim    // Check for double free first.
1030251662Sdim    if ((RsBase->isReleased() || RsBase->isRelinquished()) &&
1031249423Sdim        !didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {
1032249423Sdim      ReportDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),
1033249423Sdim                       SymBase, PreviousRetStatusSymbol);
1034249423Sdim      return 0;
1035249423Sdim
1036251662Sdim    // If the pointer is allocated or escaped, but we are now trying to free it,
1037251662Sdim    // check that the call to free is proper.
1038251662Sdim    } else if (RsBase->isAllocated() || RsBase->isEscaped()) {
1039251662Sdim
1040251662Sdim      // Check if an expected deallocation function matches the real one.
1041251662Sdim      bool DeallocMatchesAlloc =
1042251662Sdim        RsBase->getAllocationFamily() == getAllocationFamily(C, ParentExpr);
1043251662Sdim      if (!DeallocMatchesAlloc) {
1044251662Sdim        ReportMismatchedDealloc(C, ArgExpr->getSourceRange(),
1045263508Sdim                                ParentExpr, RsBase, SymBase, Hold);
1046251662Sdim        return 0;
1047251662Sdim      }
1048251662Sdim
1049251662Sdim      // Check if the memory location being freed is the actual location
1050251662Sdim      // allocated, or an offset.
1051251662Sdim      RegionOffset Offset = R->getAsOffset();
1052251662Sdim      if (Offset.isValid() &&
1053251662Sdim          !Offset.hasSymbolicOffset() &&
1054251662Sdim          Offset.getOffset() != 0) {
1055251662Sdim        const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
1056251662Sdim        ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
1057251662Sdim                         AllocExpr);
1058251662Sdim        return 0;
1059251662Sdim      }
1060249423Sdim    }
1061218887Sdim  }
1062218887Sdim
1063263508Sdim  ReleasedAllocated = (RsBase != 0) && RsBase->isAllocated();
1064243830Sdim
1065243830Sdim  // Clean out the info on previous call to free return info.
1066249423Sdim  State = State->remove<FreeReturnValue>(SymBase);
1067243830Sdim
1068243830Sdim  // Keep track of the return value. If it is NULL, we will know that free
1069243830Sdim  // failed.
1070243830Sdim  if (ReturnsNullOnFailure) {
1071243830Sdim    SVal RetVal = C.getSVal(ParentExpr);
1072243830Sdim    SymbolRef RetStatusSymbol = RetVal.getAsSymbol();
1073243830Sdim    if (RetStatusSymbol) {
1074249423Sdim      C.getSymbolManager().addSymbolDependency(SymBase, RetStatusSymbol);
1075249423Sdim      State = State->set<FreeReturnValue>(SymBase, RetStatusSymbol);
1076243830Sdim    }
1077243830Sdim  }
1078243830Sdim
1079251662Sdim  AllocationFamily Family = RsBase ? RsBase->getAllocationFamily()
1080251662Sdim                                   : getAllocationFamily(C, ParentExpr);
1081218887Sdim  // Normal free.
1082218887Sdim  if (Hold)
1083249423Sdim    return State->set<RegionState>(SymBase,
1084249423Sdim                                   RefState::getRelinquished(Family,
1085249423Sdim                                                             ParentExpr));
1086249423Sdim
1087249423Sdim  return State->set<RegionState>(SymBase,
1088249423Sdim                                 RefState::getReleased(Family, ParentExpr));
1089218887Sdim}
1090218887Sdim
1091251662Sdimbool MallocChecker::isTrackedByCurrentChecker(AllocationFamily Family) const {
1092249423Sdim  switch (Family) {
1093249423Sdim  case AF_Malloc: {
1094249423Sdim    if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic)
1095249423Sdim      return false;
1096249423Sdim    return true;
1097249423Sdim  }
1098249423Sdim  case AF_CXXNew:
1099249423Sdim  case AF_CXXNewArray: {
1100249423Sdim    if (!Filter.CNewDeleteChecker)
1101249423Sdim      return false;
1102249423Sdim    return true;
1103249423Sdim  }
1104249423Sdim  case AF_None: {
1105251662Sdim    llvm_unreachable("no family");
1106249423Sdim  }
1107249423Sdim  }
1108249423Sdim  llvm_unreachable("unhandled family");
1109249423Sdim}
1110249423Sdim
1111251662Sdimbool
1112251662SdimMallocChecker::isTrackedByCurrentChecker(CheckerContext &C,
1113251662Sdim                                         const Stmt *AllocDeallocStmt) const {
1114251662Sdim  return isTrackedByCurrentChecker(getAllocationFamily(C, AllocDeallocStmt));
1115249423Sdim}
1116249423Sdim
1117251662Sdimbool MallocChecker::isTrackedByCurrentChecker(CheckerContext &C,
1118251662Sdim                                              SymbolRef Sym) const {
1119251662Sdim
1120249423Sdim  const RefState *RS = C.getState()->get<RegionState>(Sym);
1121251662Sdim  assert(RS);
1122251662Sdim  return isTrackedByCurrentChecker(RS->getAllocationFamily());
1123249423Sdim}
1124249423Sdim
1125226633Sdimbool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
1126249423Sdim  if (Optional<nonloc::ConcreteInt> IntVal = V.getAs<nonloc::ConcreteInt>())
1127218887Sdim    os << "an integer (" << IntVal->getValue() << ")";
1128249423Sdim  else if (Optional<loc::ConcreteInt> ConstAddr = V.getAs<loc::ConcreteInt>())
1129218887Sdim    os << "a constant address (" << ConstAddr->getValue() << ")";
1130249423Sdim  else if (Optional<loc::GotoLabel> Label = V.getAs<loc::GotoLabel>())
1131218887Sdim    os << "the address of the label '" << Label->getLabel()->getName() << "'";
1132218887Sdim  else
1133218887Sdim    return false;
1134218887Sdim
1135218887Sdim  return true;
1136218887Sdim}
1137218887Sdim
1138226633Sdimbool MallocChecker::SummarizeRegion(raw_ostream &os,
1139218887Sdim                                    const MemRegion *MR) {
1140218887Sdim  switch (MR->getKind()) {
1141218887Sdim  case MemRegion::FunctionTextRegionKind: {
1142243830Sdim    const NamedDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
1143218887Sdim    if (FD)
1144226633Sdim      os << "the address of the function '" << *FD << '\'';
1145218887Sdim    else
1146218887Sdim      os << "the address of a function";
1147218887Sdim    return true;
1148218887Sdim  }
1149218887Sdim  case MemRegion::BlockTextRegionKind:
1150218887Sdim    os << "block text";
1151218887Sdim    return true;
1152218887Sdim  case MemRegion::BlockDataRegionKind:
1153218887Sdim    // FIXME: where the block came from?
1154218887Sdim    os << "a block";
1155218887Sdim    return true;
1156218887Sdim  default: {
1157218887Sdim    const MemSpaceRegion *MS = MR->getMemorySpace();
1158218887Sdim
1159234353Sdim    if (isa<StackLocalsSpaceRegion>(MS)) {
1160218887Sdim      const VarRegion *VR = dyn_cast<VarRegion>(MR);
1161218887Sdim      const VarDecl *VD;
1162218887Sdim      if (VR)
1163218887Sdim        VD = VR->getDecl();
1164218887Sdim      else
1165218887Sdim        VD = NULL;
1166218887Sdim
1167218887Sdim      if (VD)
1168218887Sdim        os << "the address of the local variable '" << VD->getName() << "'";
1169218887Sdim      else
1170218887Sdim        os << "the address of a local stack variable";
1171218887Sdim      return true;
1172218887Sdim    }
1173234353Sdim
1174234353Sdim    if (isa<StackArgumentsSpaceRegion>(MS)) {
1175218887Sdim      const VarRegion *VR = dyn_cast<VarRegion>(MR);
1176218887Sdim      const VarDecl *VD;
1177218887Sdim      if (VR)
1178218887Sdim        VD = VR->getDecl();
1179218887Sdim      else
1180218887Sdim        VD = NULL;
1181218887Sdim
1182218887Sdim      if (VD)
1183218887Sdim        os << "the address of the parameter '" << VD->getName() << "'";
1184218887Sdim      else
1185218887Sdim        os << "the address of a parameter";
1186218887Sdim      return true;
1187218887Sdim    }
1188234353Sdim
1189234353Sdim    if (isa<GlobalsSpaceRegion>(MS)) {
1190218887Sdim      const VarRegion *VR = dyn_cast<VarRegion>(MR);
1191218887Sdim      const VarDecl *VD;
1192218887Sdim      if (VR)
1193218887Sdim        VD = VR->getDecl();
1194218887Sdim      else
1195218887Sdim        VD = NULL;
1196218887Sdim
1197218887Sdim      if (VD) {
1198218887Sdim        if (VD->isStaticLocal())
1199218887Sdim          os << "the address of the static variable '" << VD->getName() << "'";
1200218887Sdim        else
1201218887Sdim          os << "the address of the global variable '" << VD->getName() << "'";
1202218887Sdim      } else
1203218887Sdim        os << "the address of a global variable";
1204218887Sdim      return true;
1205218887Sdim    }
1206234353Sdim
1207234353Sdim    return false;
1208218887Sdim  }
1209218887Sdim  }
1210218887Sdim}
1211218887Sdim
1212249423Sdimvoid MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
1213249423Sdim                                  SourceRange Range,
1214249423Sdim                                  const Expr *DeallocExpr) const {
1215249423Sdim
1216249423Sdim  if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic &&
1217249423Sdim      !Filter.CNewDeleteChecker)
1218249423Sdim    return;
1219249423Sdim
1220251662Sdim  if (!isTrackedByCurrentChecker(C, DeallocExpr))
1221249423Sdim    return;
1222249423Sdim
1223218887Sdim  if (ExplodedNode *N = C.generateSink()) {
1224218887Sdim    if (!BT_BadFree)
1225234353Sdim      BT_BadFree.reset(new BugType("Bad free", "Memory Error"));
1226218887Sdim
1227234353Sdim    SmallString<100> buf;
1228218887Sdim    llvm::raw_svector_ostream os(buf);
1229249423Sdim
1230218887Sdim    const MemRegion *MR = ArgVal.getAsRegion();
1231249423Sdim    while (const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(MR))
1232249423Sdim      MR = ER->getSuperRegion();
1233249423Sdim
1234249423Sdim    if (MR && isa<AllocaRegion>(MR))
1235249423Sdim      os << "Memory allocated by alloca() should not be deallocated";
1236249423Sdim    else {
1237249423Sdim      os << "Argument to ";
1238249423Sdim      if (!printAllocDeallocName(os, C, DeallocExpr))
1239249423Sdim        os << "deallocator";
1240249423Sdim
1241249423Sdim      os << " is ";
1242249423Sdim      bool Summarized = MR ? SummarizeRegion(os, MR)
1243249423Sdim                           : SummarizeValue(os, ArgVal);
1244249423Sdim      if (Summarized)
1245249423Sdim        os << ", which is not memory allocated by ";
1246218887Sdim      else
1247249423Sdim        os << "not memory allocated by ";
1248249423Sdim
1249249423Sdim      printExpectedAllocName(os, C, DeallocExpr);
1250218887Sdim    }
1251249423Sdim
1252226633Sdim    BugReport *R = new BugReport(*BT_BadFree, os.str(), N);
1253234353Sdim    R->markInteresting(MR);
1254249423Sdim    R->addRange(Range);
1255243830Sdim    C.emitReport(R);
1256218887Sdim  }
1257218887Sdim}
1258218887Sdim
1259249423Sdimvoid MallocChecker::ReportMismatchedDealloc(CheckerContext &C,
1260249423Sdim                                            SourceRange Range,
1261249423Sdim                                            const Expr *DeallocExpr,
1262251662Sdim                                            const RefState *RS,
1263263508Sdim                                            SymbolRef Sym,
1264263508Sdim                                            bool OwnershipTransferred) const {
1265249423Sdim
1266249423Sdim  if (!Filter.CMismatchedDeallocatorChecker)
1267249423Sdim    return;
1268249423Sdim
1269249423Sdim  if (ExplodedNode *N = C.generateSink()) {
1270249423Sdim    if (!BT_MismatchedDealloc)
1271249423Sdim      BT_MismatchedDealloc.reset(new BugType("Bad deallocator",
1272249423Sdim                                             "Memory Error"));
1273249423Sdim
1274249423Sdim    SmallString<100> buf;
1275249423Sdim    llvm::raw_svector_ostream os(buf);
1276249423Sdim
1277249423Sdim    const Expr *AllocExpr = cast<Expr>(RS->getStmt());
1278249423Sdim    SmallString<20> AllocBuf;
1279249423Sdim    llvm::raw_svector_ostream AllocOs(AllocBuf);
1280249423Sdim    SmallString<20> DeallocBuf;
1281249423Sdim    llvm::raw_svector_ostream DeallocOs(DeallocBuf);
1282249423Sdim
1283263508Sdim    if (OwnershipTransferred) {
1284263508Sdim      if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1285263508Sdim        os << DeallocOs.str() << " cannot";
1286263508Sdim      else
1287263508Sdim        os << "Cannot";
1288249423Sdim
1289263508Sdim      os << " take ownership of memory";
1290249423Sdim
1291263508Sdim      if (printAllocDeallocName(AllocOs, C, AllocExpr))
1292263508Sdim        os << " allocated by " << AllocOs.str();
1293263508Sdim    } else {
1294263508Sdim      os << "Memory";
1295263508Sdim      if (printAllocDeallocName(AllocOs, C, AllocExpr))
1296263508Sdim        os << " allocated by " << AllocOs.str();
1297249423Sdim
1298263508Sdim      os << " should be deallocated by ";
1299263508Sdim        printExpectedDeallocName(os, RS->getAllocationFamily());
1300263508Sdim
1301263508Sdim      if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
1302263508Sdim        os << ", not " << DeallocOs.str();
1303263508Sdim    }
1304263508Sdim
1305249423Sdim    BugReport *R = new BugReport(*BT_MismatchedDealloc, os.str(), N);
1306251662Sdim    R->markInteresting(Sym);
1307249423Sdim    R->addRange(Range);
1308251662Sdim    R->addVisitor(new MallocBugVisitor(Sym));
1309249423Sdim    C.emitReport(R);
1310249423Sdim  }
1311249423Sdim}
1312249423Sdim
1313249423Sdimvoid MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal,
1314249423Sdim                                     SourceRange Range, const Expr *DeallocExpr,
1315249423Sdim                                     const Expr *AllocExpr) const {
1316249423Sdim
1317249423Sdim  if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic &&
1318249423Sdim      !Filter.CNewDeleteChecker)
1319249423Sdim    return;
1320249423Sdim
1321251662Sdim  if (!isTrackedByCurrentChecker(C, AllocExpr))
1322249423Sdim    return;
1323249423Sdim
1324249423Sdim  ExplodedNode *N = C.generateSink();
1325249423Sdim  if (N == NULL)
1326249423Sdim    return;
1327249423Sdim
1328249423Sdim  if (!BT_OffsetFree)
1329249423Sdim    BT_OffsetFree.reset(new BugType("Offset free", "Memory Error"));
1330249423Sdim
1331249423Sdim  SmallString<100> buf;
1332249423Sdim  llvm::raw_svector_ostream os(buf);
1333249423Sdim  SmallString<20> AllocNameBuf;
1334249423Sdim  llvm::raw_svector_ostream AllocNameOs(AllocNameBuf);
1335249423Sdim
1336249423Sdim  const MemRegion *MR = ArgVal.getAsRegion();
1337249423Sdim  assert(MR && "Only MemRegion based symbols can have offset free errors");
1338249423Sdim
1339249423Sdim  RegionOffset Offset = MR->getAsOffset();
1340249423Sdim  assert((Offset.isValid() &&
1341249423Sdim          !Offset.hasSymbolicOffset() &&
1342249423Sdim          Offset.getOffset() != 0) &&
1343249423Sdim         "Only symbols with a valid offset can have offset free errors");
1344249423Sdim
1345249423Sdim  int offsetBytes = Offset.getOffset() / C.getASTContext().getCharWidth();
1346249423Sdim
1347249423Sdim  os << "Argument to ";
1348249423Sdim  if (!printAllocDeallocName(os, C, DeallocExpr))
1349249423Sdim    os << "deallocator";
1350249423Sdim  os << " is offset by "
1351249423Sdim     << offsetBytes
1352249423Sdim     << " "
1353249423Sdim     << ((abs(offsetBytes) > 1) ? "bytes" : "byte")
1354249423Sdim     << " from the start of ";
1355249423Sdim  if (AllocExpr && printAllocDeallocName(AllocNameOs, C, AllocExpr))
1356249423Sdim    os << "memory allocated by " << AllocNameOs.str();
1357249423Sdim  else
1358249423Sdim    os << "allocated memory";
1359249423Sdim
1360249423Sdim  BugReport *R = new BugReport(*BT_OffsetFree, os.str(), N);
1361249423Sdim  R->markInteresting(MR->getBaseRegion());
1362249423Sdim  R->addRange(Range);
1363249423Sdim  C.emitReport(R);
1364249423Sdim}
1365249423Sdim
1366249423Sdimvoid MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
1367249423Sdim                                       SymbolRef Sym) const {
1368249423Sdim
1369249423Sdim  if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic &&
1370249423Sdim      !Filter.CNewDeleteChecker)
1371249423Sdim    return;
1372249423Sdim
1373251662Sdim  if (!isTrackedByCurrentChecker(C, Sym))
1374249423Sdim    return;
1375249423Sdim
1376249423Sdim  if (ExplodedNode *N = C.generateSink()) {
1377249423Sdim    if (!BT_UseFree)
1378249423Sdim      BT_UseFree.reset(new BugType("Use-after-free", "Memory Error"));
1379249423Sdim
1380249423Sdim    BugReport *R = new BugReport(*BT_UseFree,
1381249423Sdim                                 "Use of memory after it is freed", N);
1382249423Sdim
1383249423Sdim    R->markInteresting(Sym);
1384249423Sdim    R->addRange(Range);
1385249423Sdim    R->addVisitor(new MallocBugVisitor(Sym));
1386249423Sdim    C.emitReport(R);
1387249423Sdim  }
1388249423Sdim}
1389249423Sdim
1390249423Sdimvoid MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range,
1391249423Sdim                                     bool Released, SymbolRef Sym,
1392249423Sdim                                     SymbolRef PrevSym) const {
1393249423Sdim
1394249423Sdim  if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic &&
1395249423Sdim      !Filter.CNewDeleteChecker)
1396249423Sdim    return;
1397249423Sdim
1398251662Sdim  if (!isTrackedByCurrentChecker(C, Sym))
1399249423Sdim    return;
1400249423Sdim
1401249423Sdim  if (ExplodedNode *N = C.generateSink()) {
1402249423Sdim    if (!BT_DoubleFree)
1403249423Sdim      BT_DoubleFree.reset(new BugType("Double free", "Memory Error"));
1404249423Sdim
1405249423Sdim    BugReport *R = new BugReport(*BT_DoubleFree,
1406249423Sdim      (Released ? "Attempt to free released memory"
1407249423Sdim                : "Attempt to free non-owned memory"),
1408249423Sdim      N);
1409249423Sdim    R->addRange(Range);
1410249423Sdim    R->markInteresting(Sym);
1411249423Sdim    if (PrevSym)
1412249423Sdim      R->markInteresting(PrevSym);
1413249423Sdim    R->addVisitor(new MallocBugVisitor(Sym));
1414249423Sdim    C.emitReport(R);
1415249423Sdim  }
1416249423Sdim}
1417249423Sdim
1418234353SdimProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
1419234353Sdim                                          const CallExpr *CE,
1420234353Sdim                                          bool FreesOnFail) const {
1421234353Sdim  if (CE->getNumArgs() < 2)
1422234353Sdim    return 0;
1423234353Sdim
1424234353Sdim  ProgramStateRef state = C.getState();
1425218887Sdim  const Expr *arg0Expr = CE->getArg(0);
1426234353Sdim  const LocationContext *LCtx = C.getLocationContext();
1427234353Sdim  SVal Arg0Val = state->getSVal(arg0Expr, LCtx);
1428249423Sdim  if (!Arg0Val.getAs<DefinedOrUnknownSVal>())
1429234353Sdim    return 0;
1430249423Sdim  DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
1431218887Sdim
1432218887Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
1433218887Sdim
1434218887Sdim  DefinedOrUnknownSVal PtrEQ =
1435218887Sdim    svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull());
1436218887Sdim
1437221345Sdim  // Get the size argument. If there is no size arg then give up.
1438221345Sdim  const Expr *Arg1 = CE->getArg(1);
1439221345Sdim  if (!Arg1)
1440234353Sdim    return 0;
1441221345Sdim
1442221345Sdim  // Get the value of the size argument.
1443234353Sdim  SVal Arg1ValG = state->getSVal(Arg1, LCtx);
1444249423Sdim  if (!Arg1ValG.getAs<DefinedOrUnknownSVal>())
1445234353Sdim    return 0;
1446249423Sdim  DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs<DefinedOrUnknownSVal>();
1447221345Sdim
1448221345Sdim  // Compare the size argument to 0.
1449221345Sdim  DefinedOrUnknownSVal SizeZero =
1450221345Sdim    svalBuilder.evalEQ(state, Arg1Val,
1451221345Sdim                       svalBuilder.makeIntValWithPtrWidth(0, false));
1452221345Sdim
1453234353Sdim  ProgramStateRef StatePtrIsNull, StatePtrNotNull;
1454234353Sdim  llvm::tie(StatePtrIsNull, StatePtrNotNull) = state->assume(PtrEQ);
1455234353Sdim  ProgramStateRef StateSizeIsZero, StateSizeNotZero;
1456234353Sdim  llvm::tie(StateSizeIsZero, StateSizeNotZero) = state->assume(SizeZero);
1457234353Sdim  // We only assume exceptional states if they are definitely true; if the
1458234353Sdim  // state is under-constrained, assume regular realloc behavior.
1459234353Sdim  bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
1460234353Sdim  bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
1461234353Sdim
1462221345Sdim  // If the ptr is NULL and the size is not 0, the call is equivalent to
1463221345Sdim  // malloc(size).
1464234353Sdim  if ( PrtIsNull && !SizeIsZero) {
1465234353Sdim    ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1),
1466234353Sdim                                               UndefinedVal(), StatePtrIsNull);
1467234353Sdim    return stateMalloc;
1468218887Sdim  }
1469218887Sdim
1470234353Sdim  if (PrtIsNull && SizeIsZero)
1471234353Sdim    return 0;
1472218887Sdim
1473234353Sdim  // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
1474234353Sdim  assert(!PrtIsNull);
1475234353Sdim  SymbolRef FromPtr = arg0Val.getAsSymbol();
1476234353Sdim  SVal RetVal = state->getSVal(CE, LCtx);
1477234353Sdim  SymbolRef ToPtr = RetVal.getAsSymbol();
1478234353Sdim  if (!FromPtr || !ToPtr)
1479234353Sdim    return 0;
1480234353Sdim
1481243830Sdim  bool ReleasedAllocated = false;
1482243830Sdim
1483234353Sdim  // If the size is 0, free the memory.
1484234353Sdim  if (SizeIsZero)
1485243830Sdim    if (ProgramStateRef stateFree = FreeMemAux(C, CE, StateSizeIsZero, 0,
1486243830Sdim                                               false, ReleasedAllocated)){
1487234353Sdim      // The semantics of the return value are:
1488234353Sdim      // If size was equal to 0, either NULL or a pointer suitable to be passed
1489239462Sdim      // to free() is returned. We just free the input pointer and do not add
1490239462Sdim      // any constrains on the output pointer.
1491234353Sdim      return stateFree;
1492234353Sdim    }
1493234353Sdim
1494234353Sdim  // Default behavior.
1495243830Sdim  if (ProgramStateRef stateFree =
1496243830Sdim        FreeMemAux(C, CE, state, 0, false, ReleasedAllocated)) {
1497243830Sdim
1498234353Sdim    ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
1499234353Sdim                                                UnknownVal(), stateFree);
1500234353Sdim    if (!stateRealloc)
1501234353Sdim      return 0;
1502243830Sdim
1503243830Sdim    ReallocPairKind Kind = RPToBeFreedAfterFailure;
1504243830Sdim    if (FreesOnFail)
1505243830Sdim      Kind = RPIsFreeOnFailure;
1506243830Sdim    else if (!ReleasedAllocated)
1507243830Sdim      Kind = RPDoNotTrackAfterFailure;
1508243830Sdim
1509243830Sdim    // Record the info about the reallocated symbol so that we could properly
1510243830Sdim    // process failed reallocation.
1511234353Sdim    stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
1512243830Sdim                                                   ReallocPair(FromPtr, Kind));
1513243830Sdim    // The reallocated symbol should stay alive for as long as the new symbol.
1514234353Sdim    C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
1515234353Sdim    return stateRealloc;
1516218887Sdim  }
1517234353Sdim  return 0;
1518218887Sdim}
1519218887Sdim
1520234353SdimProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){
1521234353Sdim  if (CE->getNumArgs() < 2)
1522234353Sdim    return 0;
1523234353Sdim
1524234353Sdim  ProgramStateRef state = C.getState();
1525218887Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
1526234353Sdim  const LocationContext *LCtx = C.getLocationContext();
1527234353Sdim  SVal count = state->getSVal(CE->getArg(0), LCtx);
1528234353Sdim  SVal elementSize = state->getSVal(CE->getArg(1), LCtx);
1529218887Sdim  SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize,
1530218887Sdim                                        svalBuilder.getContext().getSizeType());
1531218887Sdim  SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
1532218887Sdim
1533234353Sdim  return MallocMemAux(C, CE, TotalSize, zeroVal, state);
1534218887Sdim}
1535218887Sdim
1536234353SdimLeakInfo
1537234353SdimMallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
1538234353Sdim                                 CheckerContext &C) const {
1539234353Sdim  const LocationContext *LeakContext = N->getLocationContext();
1540234353Sdim  // Walk the ExplodedGraph backwards and find the first node that referred to
1541234353Sdim  // the tracked symbol.
1542234353Sdim  const ExplodedNode *AllocNode = N;
1543234353Sdim  const MemRegion *ReferenceRegion = 0;
1544234353Sdim
1545234353Sdim  while (N) {
1546234353Sdim    ProgramStateRef State = N->getState();
1547234353Sdim    if (!State->get<RegionState>(Sym))
1548234353Sdim      break;
1549234353Sdim
1550234353Sdim    // Find the most recent expression bound to the symbol in the current
1551234353Sdim    // context.
1552251662Sdim      if (!ReferenceRegion) {
1553251662Sdim        if (const MemRegion *MR = C.getLocationRegionIfPostStore(N)) {
1554251662Sdim          SVal Val = State->getSVal(MR);
1555251662Sdim          if (Val.getAsLocSymbol() == Sym) {
1556251662Sdim            const VarRegion* VR = MR->getBaseRegion()->getAs<VarRegion>();
1557251662Sdim            // Do not show local variables belonging to a function other than
1558251662Sdim            // where the error is reported.
1559251662Sdim            if (!VR ||
1560251662Sdim                (VR->getStackFrame() == LeakContext->getCurrentStackFrame()))
1561251662Sdim              ReferenceRegion = MR;
1562251662Sdim          }
1563251662Sdim        }
1564234353Sdim      }
1565234353Sdim
1566234353Sdim    // Allocation node, is the last node in the current context in which the
1567234353Sdim    // symbol was tracked.
1568234353Sdim    if (N->getLocationContext() == LeakContext)
1569234353Sdim      AllocNode = N;
1570234353Sdim    N = N->pred_empty() ? NULL : *(N->pred_begin());
1571234353Sdim  }
1572234353Sdim
1573249423Sdim  return LeakInfo(AllocNode, ReferenceRegion);
1574234353Sdim}
1575234353Sdim
1576234353Sdimvoid MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
1577234353Sdim                               CheckerContext &C) const {
1578249423Sdim
1579249423Sdim  if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic &&
1580251662Sdim      !Filter.CNewDeleteLeaksChecker)
1581249423Sdim    return;
1582249423Sdim
1583251662Sdim  const RefState *RS = C.getState()->get<RegionState>(Sym);
1584251662Sdim  assert(RS && "cannot leak an untracked symbol");
1585251662Sdim  AllocationFamily Family = RS->getAllocationFamily();
1586251662Sdim  if (!isTrackedByCurrentChecker(Family))
1587249423Sdim    return;
1588249423Sdim
1589251662Sdim  // Special case for new and new[]; these are controlled by a separate checker
1590251662Sdim  // flag so that they can be selectively disabled.
1591251662Sdim  if (Family == AF_CXXNew || Family == AF_CXXNewArray)
1592251662Sdim    if (!Filter.CNewDeleteLeaksChecker)
1593251662Sdim      return;
1594251662Sdim
1595234353Sdim  assert(N);
1596234353Sdim  if (!BT_Leak) {
1597234353Sdim    BT_Leak.reset(new BugType("Memory leak", "Memory Error"));
1598234353Sdim    // Leaks should not be reported if they are post-dominated by a sink:
1599234353Sdim    // (1) Sinks are higher importance bugs.
1600234353Sdim    // (2) NoReturnFunctionChecker uses sink nodes to represent paths ending
1601234353Sdim    //     with __noreturn functions such as assert() or exit(). We choose not
1602234353Sdim    //     to report leaks on such paths.
1603234353Sdim    BT_Leak->setSuppressOnSink(true);
1604234353Sdim  }
1605234353Sdim
1606234353Sdim  // Most bug reports are cached at the location where they occurred.
1607234353Sdim  // With leaks, we want to unique them by the location where they were
1608234353Sdim  // allocated, and only report a single path.
1609234353Sdim  PathDiagnosticLocation LocUsedForUniqueing;
1610249423Sdim  const ExplodedNode *AllocNode = 0;
1611234353Sdim  const MemRegion *Region = 0;
1612249423Sdim  llvm::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
1613249423Sdim
1614249423Sdim  ProgramPoint P = AllocNode->getLocation();
1615249423Sdim  const Stmt *AllocationStmt = 0;
1616249423Sdim  if (Optional<CallExitEnd> Exit = P.getAs<CallExitEnd>())
1617249423Sdim    AllocationStmt = Exit->getCalleeContext()->getCallSite();
1618249423Sdim  else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
1619249423Sdim    AllocationStmt = SP->getStmt();
1620249423Sdim  if (AllocationStmt)
1621249423Sdim    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt,
1622249423Sdim                                              C.getSourceManager(),
1623249423Sdim                                              AllocNode->getLocationContext());
1624234353Sdim
1625234353Sdim  SmallString<200> buf;
1626234353Sdim  llvm::raw_svector_ostream os(buf);
1627239462Sdim  if (Region && Region->canPrintPretty()) {
1628251662Sdim    os << "Potential leak of memory pointed to by ";
1629239462Sdim    Region->printPretty(os);
1630251662Sdim  } else {
1631251662Sdim    os << "Potential memory leak";
1632234353Sdim  }
1633234353Sdim
1634249423Sdim  BugReport *R = new BugReport(*BT_Leak, os.str(), N,
1635249423Sdim                               LocUsedForUniqueing,
1636249423Sdim                               AllocNode->getLocationContext()->getDecl());
1637234353Sdim  R->markInteresting(Sym);
1638239462Sdim  R->addVisitor(new MallocBugVisitor(Sym, true));
1639243830Sdim  C.emitReport(R);
1640234353Sdim}
1641234353Sdim
1642221345Sdimvoid MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1643221345Sdim                                     CheckerContext &C) const
1644218887Sdim{
1645218887Sdim  if (!SymReaper.hasDeadSymbols())
1646218887Sdim    return;
1647218887Sdim
1648234353Sdim  ProgramStateRef state = C.getState();
1649218887Sdim  RegionStateTy RS = state->get<RegionState>();
1650218887Sdim  RegionStateTy::Factory &F = state->get_context<RegionState>();
1651218887Sdim
1652249423Sdim  SmallVector<SymbolRef, 2> Errors;
1653218887Sdim  for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
1654218887Sdim    if (SymReaper.isDead(I->first)) {
1655243830Sdim      if (I->second.isAllocated())
1656234353Sdim        Errors.push_back(I->first);
1657218887Sdim      // Remove the dead symbol from the map.
1658218887Sdim      RS = F.remove(RS, I->first);
1659226633Sdim
1660218887Sdim    }
1661218887Sdim  }
1662226633Sdim
1663234353Sdim  // Cleanup the Realloc Pairs Map.
1664243830Sdim  ReallocPairsTy RP = state->get<ReallocPairs>();
1665243830Sdim  for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
1666234353Sdim    if (SymReaper.isDead(I->first) ||
1667234353Sdim        SymReaper.isDead(I->second.ReallocatedSym)) {
1668234353Sdim      state = state->remove<ReallocPairs>(I->first);
1669234353Sdim    }
1670234353Sdim  }
1671226633Sdim
1672243830Sdim  // Cleanup the FreeReturnValue Map.
1673243830Sdim  FreeReturnValueTy FR = state->get<FreeReturnValue>();
1674243830Sdim  for (FreeReturnValueTy::iterator I = FR.begin(), E = FR.end(); I != E; ++I) {
1675243830Sdim    if (SymReaper.isDead(I->first) ||
1676243830Sdim        SymReaper.isDead(I->second)) {
1677243830Sdim      state = state->remove<FreeReturnValue>(I->first);
1678243830Sdim    }
1679243830Sdim  }
1680243830Sdim
1681234353Sdim  // Generate leak node.
1682243830Sdim  ExplodedNode *N = C.getPredecessor();
1683243830Sdim  if (!Errors.empty()) {
1684243830Sdim    static SimpleProgramPointTag Tag("MallocChecker : DeadSymbolsLeak");
1685243830Sdim    N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
1686263508Sdim    for (SmallVectorImpl<SymbolRef>::iterator
1687263508Sdim           I = Errors.begin(), E = Errors.end(); I != E; ++I) {
1688234353Sdim      reportLeak(*I, N, C);
1689234353Sdim    }
1690226633Sdim  }
1691243830Sdim
1692234353Sdim  C.addTransition(state->set<RegionState>(RS), N);
1693218887Sdim}
1694218887Sdim
1695251662Sdimvoid MallocChecker::checkPreCall(const CallEvent &Call,
1696251662Sdim                                 CheckerContext &C) const {
1697251662Sdim
1698239462Sdim  // We will check for double free in the post visit.
1699251662Sdim  if (const AnyFunctionCall *FC = dyn_cast<AnyFunctionCall>(&Call)) {
1700251662Sdim    const FunctionDecl *FD = FC->getDecl();
1701251662Sdim    if (!FD)
1702251662Sdim      return;
1703234353Sdim
1704251662Sdim    if ((Filter.CMallocOptimistic || Filter.CMallocPessimistic) &&
1705251662Sdim        isFreeFunction(FD, C.getASTContext()))
1706251662Sdim      return;
1707249423Sdim
1708251662Sdim    if (Filter.CNewDeleteChecker &&
1709251662Sdim        isStandardNewDelete(FD, C.getASTContext()))
1710251662Sdim      return;
1711251662Sdim  }
1712251662Sdim
1713251662Sdim  // Check if the callee of a method is deleted.
1714251662Sdim  if (const CXXInstanceCall *CC = dyn_cast<CXXInstanceCall>(&Call)) {
1715251662Sdim    SymbolRef Sym = CC->getCXXThisVal().getAsSymbol();
1716251662Sdim    if (!Sym || checkUseAfterFree(Sym, C, CC->getCXXThisExpr()))
1717251662Sdim      return;
1718251662Sdim  }
1719251662Sdim
1720251662Sdim  // Check arguments for being used after free.
1721251662Sdim  for (unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) {
1722251662Sdim    SVal ArgSVal = Call.getArgSVal(I);
1723251662Sdim    if (ArgSVal.getAs<Loc>()) {
1724251662Sdim      SymbolRef Sym = ArgSVal.getAsSymbol();
1725234353Sdim      if (!Sym)
1726234353Sdim        continue;
1727251662Sdim      if (checkUseAfterFree(Sym, C, Call.getArgExpr(I)))
1728234353Sdim        return;
1729234353Sdim    }
1730234353Sdim  }
1731234353Sdim}
1732234353Sdim
1733221345Sdimvoid MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
1734234353Sdim  const Expr *E = S->getRetValue();
1735234353Sdim  if (!E)
1736218887Sdim    return;
1737218887Sdim
1738234353Sdim  // Check if we are returning a symbol.
1739239462Sdim  ProgramStateRef State = C.getState();
1740239462Sdim  SVal RetVal = State->getSVal(E, C.getLocationContext());
1741234353Sdim  SymbolRef Sym = RetVal.getAsSymbol();
1742218887Sdim  if (!Sym)
1743234353Sdim    // If we are returning a field of the allocated struct or an array element,
1744234353Sdim    // the callee could still free the memory.
1745234353Sdim    // TODO: This logic should be a part of generic symbol escape callback.
1746234353Sdim    if (const MemRegion *MR = RetVal.getAsRegion())
1747234353Sdim      if (isa<FieldRegion>(MR) || isa<ElementRegion>(MR))
1748234353Sdim        if (const SymbolicRegion *BMR =
1749234353Sdim              dyn_cast<SymbolicRegion>(MR->getBaseRegion()))
1750234353Sdim          Sym = BMR->getSymbol();
1751218887Sdim
1752234353Sdim  // Check if we are returning freed memory.
1753239462Sdim  if (Sym)
1754249423Sdim    checkUseAfterFree(Sym, C, E);
1755218887Sdim}
1756218887Sdim
1757234353Sdim// TODO: Blocks should be either inlined or should call invalidate regions
1758234353Sdim// upon invocation. After that's in place, special casing here will not be
1759234353Sdim// needed.
1760234353Sdimvoid MallocChecker::checkPostStmt(const BlockExpr *BE,
1761234353Sdim                                  CheckerContext &C) const {
1762218887Sdim
1763234353Sdim  // Scan the BlockDecRefExprs for any object the retain count checker
1764234353Sdim  // may be tracking.
1765234353Sdim  if (!BE->getBlockDecl()->hasCaptures())
1766234353Sdim    return;
1767218887Sdim
1768234353Sdim  ProgramStateRef state = C.getState();
1769234353Sdim  const BlockDataRegion *R =
1770234353Sdim    cast<BlockDataRegion>(state->getSVal(BE,
1771234353Sdim                                         C.getLocationContext()).getAsRegion());
1772234353Sdim
1773234353Sdim  BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
1774234353Sdim                                            E = R->referenced_vars_end();
1775234353Sdim
1776234353Sdim  if (I == E)
1777234353Sdim    return;
1778234353Sdim
1779234353Sdim  SmallVector<const MemRegion*, 10> Regions;
1780234353Sdim  const LocationContext *LC = C.getLocationContext();
1781234353Sdim  MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
1782234353Sdim
1783234353Sdim  for ( ; I != E; ++I) {
1784249423Sdim    const VarRegion *VR = I.getCapturedRegion();
1785234353Sdim    if (VR->getSuperRegion() == R) {
1786234353Sdim      VR = MemMgr.getVarRegion(VR->getDecl(), LC);
1787234353Sdim    }
1788234353Sdim    Regions.push_back(VR);
1789218887Sdim  }
1790218887Sdim
1791234353Sdim  state =
1792234353Sdim    state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
1793234353Sdim                                    Regions.data() + Regions.size()).getState();
1794234353Sdim  C.addTransition(state);
1795218887Sdim}
1796218887Sdim
1797239462Sdimbool MallocChecker::isReleased(SymbolRef Sym, CheckerContext &C) const {
1798239462Sdim  assert(Sym);
1799239462Sdim  const RefState *RS = C.getState()->get<RegionState>(Sym);
1800239462Sdim  return (RS && RS->isReleased());
1801239462Sdim}
1802239462Sdim
1803234353Sdimbool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
1804234353Sdim                                      const Stmt *S) const {
1805249423Sdim
1806263508Sdim  // FIXME: Handle destructor called from delete more precisely.
1807263508Sdim  if (isReleased(Sym, C) && S) {
1808249423Sdim    ReportUseAfterFree(C, S->getSourceRange(), Sym);
1809249423Sdim    return true;
1810249423Sdim  }
1811234353Sdim
1812234353Sdim  return false;
1813234353Sdim}
1814234353Sdim
1815218887Sdim// Check if the location is a freed symbolic region.
1816226633Sdimvoid MallocChecker::checkLocation(SVal l, bool isLoad, const Stmt *S,
1817226633Sdim                                  CheckerContext &C) const {
1818218887Sdim  SymbolRef Sym = l.getLocSymbolInBase();
1819234353Sdim  if (Sym)
1820239462Sdim    checkUseAfterFree(Sym, C, S);
1821234353Sdim}
1822218887Sdim
1823234353Sdim// If a symbolic region is assumed to NULL (or another constant), stop tracking
1824234353Sdim// it - assuming that allocation failed on this path.
1825234353SdimProgramStateRef MallocChecker::evalAssume(ProgramStateRef state,
1826234353Sdim                                              SVal Cond,
1827234353Sdim                                              bool Assumption) const {
1828234353Sdim  RegionStateTy RS = state->get<RegionState>();
1829234353Sdim  for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
1830243830Sdim    // If the symbol is assumed to be NULL, remove it from consideration.
1831243830Sdim    ConstraintManager &CMgr = state->getConstraintManager();
1832243830Sdim    ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
1833243830Sdim    if (AllocFailed.isConstrainedTrue())
1834234353Sdim      state = state->remove<RegionState>(I.getKey());
1835234353Sdim  }
1836234353Sdim
1837234353Sdim  // Realloc returns 0 when reallocation fails, which means that we should
1838234353Sdim  // restore the state of the pointer being reallocated.
1839243830Sdim  ReallocPairsTy RP = state->get<ReallocPairs>();
1840243830Sdim  for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
1841243830Sdim    // If the symbol is assumed to be NULL, remove it from consideration.
1842243830Sdim    ConstraintManager &CMgr = state->getConstraintManager();
1843243830Sdim    ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
1844243830Sdim    if (!AllocFailed.isConstrainedTrue())
1845243830Sdim      continue;
1846243830Sdim
1847243830Sdim    SymbolRef ReallocSym = I.getData().ReallocatedSym;
1848243830Sdim    if (const RefState *RS = state->get<RegionState>(ReallocSym)) {
1849243830Sdim      if (RS->isReleased()) {
1850243830Sdim        if (I.getData().Kind == RPToBeFreedAfterFailure)
1851234353Sdim          state = state->set<RegionState>(ReallocSym,
1852249423Sdim              RefState::getAllocated(RS->getAllocationFamily(), RS->getStmt()));
1853243830Sdim        else if (I.getData().Kind == RPDoNotTrackAfterFailure)
1854243830Sdim          state = state->remove<RegionState>(ReallocSym);
1855243830Sdim        else
1856243830Sdim          assert(I.getData().Kind == RPIsFreeOnFailure);
1857218887Sdim      }
1858218887Sdim    }
1859243830Sdim    state = state->remove<ReallocPairs>(I.getKey());
1860218887Sdim  }
1861234353Sdim
1862234353Sdim  return state;
1863218887Sdim}
1864218887Sdim
1865263508Sdimbool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
1866263508Sdim                                              const CallEvent *Call,
1867263508Sdim                                              ProgramStateRef State,
1868263508Sdim                                              SymbolRef &EscapingSymbol) const {
1869239462Sdim  assert(Call);
1870263508Sdim  EscapingSymbol = 0;
1871263508Sdim
1872234353Sdim  // For now, assume that any C++ call can free memory.
1873234353Sdim  // TODO: If we want to be more optimistic here, we'll need to make sure that
1874234353Sdim  // regions escape to C++ containers. They seem to do that even now, but for
1875234353Sdim  // mysterious reasons.
1876239462Sdim  if (!(isa<FunctionCall>(Call) || isa<ObjCMethodCall>(Call)))
1877263508Sdim    return true;
1878218887Sdim
1879239462Sdim  // Check Objective-C messages by selector name.
1880239462Sdim  if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
1881239462Sdim    // If it's not a framework call, or if it takes a callback, assume it
1882239462Sdim    // can free memory.
1883239462Sdim    if (!Call->isInSystemHeader() || Call->hasNonZeroCallbackArg())
1884263508Sdim      return true;
1885218887Sdim
1886249423Sdim    // If it's a method we know about, handle it explicitly post-call.
1887249423Sdim    // This should happen before the "freeWhenDone" check below.
1888249423Sdim    if (isKnownDeallocObjCMethodName(*Msg))
1889263508Sdim      return false;
1890234353Sdim
1891249423Sdim    // If there's a "freeWhenDone" parameter, but the method isn't one we know
1892249423Sdim    // about, we can't be sure that the object will use free() to deallocate the
1893249423Sdim    // memory, so we can't model it explicitly. The best we can do is use it to
1894249423Sdim    // decide whether the pointer escapes.
1895249423Sdim    if (Optional<bool> FreeWhenDone = getFreeWhenDoneArg(*Msg))
1896263508Sdim      return *FreeWhenDone;
1897234353Sdim
1898249423Sdim    // If the first selector piece ends with "NoCopy", and there is no
1899249423Sdim    // "freeWhenDone" parameter set to zero, we know ownership is being
1900249423Sdim    // transferred. Again, though, we can't be sure that the object will use
1901249423Sdim    // free() to deallocate the memory, so we can't model it explicitly.
1902249423Sdim    StringRef FirstSlot = Msg->getSelector().getNameForSlot(0);
1903239462Sdim    if (FirstSlot.endswith("NoCopy"))
1904263508Sdim      return true;
1905239462Sdim
1906239462Sdim    // If the first selector starts with addPointer, insertPointer,
1907239462Sdim    // or replacePointer, assume we are dealing with NSPointerArray or similar.
1908239462Sdim    // This is similar to C++ containers (vector); we still might want to check
1909239462Sdim    // that the pointers get freed by following the container itself.
1910239462Sdim    if (FirstSlot.startswith("addPointer") ||
1911239462Sdim        FirstSlot.startswith("insertPointer") ||
1912239462Sdim        FirstSlot.startswith("replacePointer")) {
1913263508Sdim      return true;
1914234353Sdim    }
1915234353Sdim
1916263508Sdim    // We should escape receiver on call to 'init'. This is especially relevant
1917263508Sdim    // to the receiver, as the corresponding symbol is usually not referenced
1918263508Sdim    // after the call.
1919263508Sdim    if (Msg->getMethodFamily() == OMF_init) {
1920263508Sdim      EscapingSymbol = Msg->getReceiverSVal().getAsSymbol();
1921263508Sdim      return true;
1922263508Sdim    }
1923263508Sdim
1924239462Sdim    // Otherwise, assume that the method does not free memory.
1925239462Sdim    // Most framework methods do not free memory.
1926263508Sdim    return false;
1927218887Sdim  }
1928234353Sdim
1929239462Sdim  // At this point the only thing left to handle is straight function calls.
1930239462Sdim  const FunctionDecl *FD = cast<FunctionCall>(Call)->getDecl();
1931239462Sdim  if (!FD)
1932263508Sdim    return true;
1933234353Sdim
1934239462Sdim  ASTContext &ASTC = State->getStateManager().getContext();
1935239462Sdim
1936239462Sdim  // If it's one of the allocation functions we can reason about, we model
1937239462Sdim  // its behavior explicitly.
1938239462Sdim  if (isMemFunction(FD, ASTC))
1939263508Sdim    return false;
1940239462Sdim
1941239462Sdim  // If it's not a system call, assume it frees memory.
1942239462Sdim  if (!Call->isInSystemHeader())
1943263508Sdim    return true;
1944239462Sdim
1945239462Sdim  // White list the system functions whose arguments escape.
1946239462Sdim  const IdentifierInfo *II = FD->getIdentifier();
1947239462Sdim  if (!II)
1948263508Sdim    return true;
1949239462Sdim  StringRef FName = II->getName();
1950239462Sdim
1951239462Sdim  // White list the 'XXXNoCopy' CoreFoundation functions.
1952239462Sdim  // We specifically check these before
1953239462Sdim  if (FName.endswith("NoCopy")) {
1954239462Sdim    // Look for the deallocator argument. We know that the memory ownership
1955239462Sdim    // is not transferred only if the deallocator argument is
1956239462Sdim    // 'kCFAllocatorNull'.
1957239462Sdim    for (unsigned i = 1; i < Call->getNumArgs(); ++i) {
1958239462Sdim      const Expr *ArgE = Call->getArgExpr(i)->IgnoreParenCasts();
1959239462Sdim      if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) {
1960239462Sdim        StringRef DeallocatorName = DE->getFoundDecl()->getName();
1961239462Sdim        if (DeallocatorName == "kCFAllocatorNull")
1962263508Sdim          return false;
1963239462Sdim      }
1964239462Sdim    }
1965263508Sdim    return true;
1966239462Sdim  }
1967239462Sdim
1968239462Sdim  // Associating streams with malloced buffers. The pointer can escape if
1969239462Sdim  // 'closefn' is specified (and if that function does free memory),
1970239462Sdim  // but it will not if closefn is not specified.
1971239462Sdim  // Currently, we do not inspect the 'closefn' function (PR12101).
1972239462Sdim  if (FName == "funopen")
1973239462Sdim    if (Call->getNumArgs() >= 4 && Call->getArgSVal(4).isConstant(0))
1974263508Sdim      return false;
1975239462Sdim
1976239462Sdim  // Do not warn on pointers passed to 'setbuf' when used with std streams,
1977239462Sdim  // these leaks might be intentional when setting the buffer for stdio.
1978239462Sdim  // http://stackoverflow.com/questions/2671151/who-frees-setvbuf-buffer
1979239462Sdim  if (FName == "setbuf" || FName =="setbuffer" ||
1980239462Sdim      FName == "setlinebuf" || FName == "setvbuf") {
1981239462Sdim    if (Call->getNumArgs() >= 1) {
1982239462Sdim      const Expr *ArgE = Call->getArgExpr(0)->IgnoreParenCasts();
1983239462Sdim      if (const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE))
1984239462Sdim        if (const VarDecl *D = dyn_cast<VarDecl>(ArgDRE->getDecl()))
1985239462Sdim          if (D->getCanonicalDecl()->getName().find("std") != StringRef::npos)
1986263508Sdim            return true;
1987239462Sdim    }
1988239462Sdim  }
1989239462Sdim
1990239462Sdim  // A bunch of other functions which either take ownership of a pointer or
1991239462Sdim  // wrap the result up in a struct or object, meaning it can be freed later.
1992239462Sdim  // (See RetainCountChecker.) Not all the parameters here are invalidated,
1993239462Sdim  // but the Malloc checker cannot differentiate between them. The right way
1994239462Sdim  // of doing this would be to implement a pointer escapes callback.
1995239462Sdim  if (FName == "CGBitmapContextCreate" ||
1996239462Sdim      FName == "CGBitmapContextCreateWithData" ||
1997239462Sdim      FName == "CVPixelBufferCreateWithBytes" ||
1998239462Sdim      FName == "CVPixelBufferCreateWithPlanarBytes" ||
1999239462Sdim      FName == "OSAtomicEnqueue") {
2000263508Sdim    return true;
2001239462Sdim  }
2002239462Sdim
2003239462Sdim  // Handle cases where we know a buffer's /address/ can escape.
2004239462Sdim  // Note that the above checks handle some special cases where we know that
2005239462Sdim  // even though the address escapes, it's still our responsibility to free the
2006239462Sdim  // buffer.
2007239462Sdim  if (Call->argumentsMayEscape())
2008263508Sdim    return true;
2009239462Sdim
2010239462Sdim  // Otherwise, assume that the function does not free memory.
2011239462Sdim  // Most system calls do not free the memory.
2012263508Sdim  return false;
2013218887Sdim}
2014221345Sdim
2015249423Sdimstatic bool retTrue(const RefState *RS) {
2016249423Sdim  return true;
2017249423Sdim}
2018234353Sdim
2019249423Sdimstatic bool checkIfNewOrNewArrayFamily(const RefState *RS) {
2020249423Sdim  return (RS->getAllocationFamily() == AF_CXXNewArray ||
2021249423Sdim          RS->getAllocationFamily() == AF_CXXNew);
2022249423Sdim}
2023234353Sdim
2024249423SdimProgramStateRef MallocChecker::checkPointerEscape(ProgramStateRef State,
2025249423Sdim                                             const InvalidatedSymbols &Escaped,
2026249423Sdim                                             const CallEvent *Call,
2027249423Sdim                                             PointerEscapeKind Kind) const {
2028249423Sdim  return checkPointerEscapeAux(State, Escaped, Call, Kind, &retTrue);
2029249423Sdim}
2030249423Sdim
2031249423SdimProgramStateRef MallocChecker::checkConstPointerEscape(ProgramStateRef State,
2032249423Sdim                                              const InvalidatedSymbols &Escaped,
2033249423Sdim                                              const CallEvent *Call,
2034249423Sdim                                              PointerEscapeKind Kind) const {
2035249423Sdim  return checkPointerEscapeAux(State, Escaped, Call, Kind,
2036249423Sdim                               &checkIfNewOrNewArrayFamily);
2037249423Sdim}
2038249423Sdim
2039249423SdimProgramStateRef MallocChecker::checkPointerEscapeAux(ProgramStateRef State,
2040249423Sdim                                              const InvalidatedSymbols &Escaped,
2041249423Sdim                                              const CallEvent *Call,
2042249423Sdim                                              PointerEscapeKind Kind,
2043249423Sdim                                  bool(*CheckRefState)(const RefState*)) const {
2044249423Sdim  // If we know that the call does not free memory, or we want to process the
2045249423Sdim  // call later, keep tracking the top level arguments.
2046263508Sdim  SymbolRef EscapingSymbol = 0;
2047263508Sdim  if (Kind == PSK_DirectEscapeOnCall &&
2048263508Sdim      !mayFreeAnyEscapedMemoryOrIsModeledExplicitly(Call, State,
2049263508Sdim                                                    EscapingSymbol) &&
2050263508Sdim      !EscapingSymbol) {
2051249423Sdim    return State;
2052234353Sdim  }
2053234353Sdim
2054249423Sdim  for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
2055249423Sdim       E = Escaped.end();
2056249423Sdim       I != E; ++I) {
2057234353Sdim    SymbolRef sym = *I;
2058249423Sdim
2059263508Sdim    if (EscapingSymbol && EscapingSymbol != sym)
2060263508Sdim      continue;
2061263508Sdim
2062239462Sdim    if (const RefState *RS = State->get<RegionState>(sym)) {
2063251662Sdim      if (RS->isAllocated() && CheckRefState(RS)) {
2064239462Sdim        State = State->remove<RegionState>(sym);
2065251662Sdim        State = State->set<RegionState>(sym, RefState::getEscaped(RS));
2066251662Sdim      }
2067239462Sdim    }
2068234353Sdim  }
2069234353Sdim  return State;
2070221345Sdim}
2071234353Sdim
2072234353Sdimstatic SymbolRef findFailedReallocSymbol(ProgramStateRef currState,
2073234353Sdim                                         ProgramStateRef prevState) {
2074243830Sdim  ReallocPairsTy currMap = currState->get<ReallocPairs>();
2075243830Sdim  ReallocPairsTy prevMap = prevState->get<ReallocPairs>();
2076234353Sdim
2077243830Sdim  for (ReallocPairsTy::iterator I = prevMap.begin(), E = prevMap.end();
2078234353Sdim       I != E; ++I) {
2079234353Sdim    SymbolRef sym = I.getKey();
2080234353Sdim    if (!currMap.lookup(sym))
2081234353Sdim      return sym;
2082234353Sdim  }
2083234353Sdim
2084234353Sdim  return NULL;
2085234353Sdim}
2086234353Sdim
2087234353SdimPathDiagnosticPiece *
2088234353SdimMallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
2089234353Sdim                                           const ExplodedNode *PrevN,
2090234353Sdim                                           BugReporterContext &BRC,
2091234353Sdim                                           BugReport &BR) {
2092234353Sdim  ProgramStateRef state = N->getState();
2093234353Sdim  ProgramStateRef statePrev = PrevN->getState();
2094234353Sdim
2095234353Sdim  const RefState *RS = state->get<RegionState>(Sym);
2096234353Sdim  const RefState *RSPrev = statePrev->get<RegionState>(Sym);
2097239462Sdim  if (!RS)
2098234353Sdim    return 0;
2099234353Sdim
2100234353Sdim  const Stmt *S = 0;
2101234353Sdim  const char *Msg = 0;
2102234353Sdim  StackHintGeneratorForSymbol *StackHint = 0;
2103234353Sdim
2104234353Sdim  // Retrieve the associated statement.
2105234353Sdim  ProgramPoint ProgLoc = N->getLocation();
2106249423Sdim  if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
2107239462Sdim    S = SP->getStmt();
2108249423Sdim  } else if (Optional<CallExitEnd> Exit = ProgLoc.getAs<CallExitEnd>()) {
2109239462Sdim    S = Exit->getCalleeContext()->getCallSite();
2110249423Sdim  } else if (Optional<BlockEdge> Edge = ProgLoc.getAs<BlockEdge>()) {
2111249423Sdim    // If an assumption was made on a branch, it should be caught
2112249423Sdim    // here by looking at the state transition.
2113249423Sdim    S = Edge->getSrc()->getTerminator();
2114234353Sdim  }
2115249423Sdim
2116234353Sdim  if (!S)
2117234353Sdim    return 0;
2118234353Sdim
2119239462Sdim  // FIXME: We will eventually need to handle non-statement-based events
2120239462Sdim  // (__attribute__((cleanup))).
2121239462Sdim
2122234353Sdim  // Find out if this is an interesting point and what is the kind.
2123234353Sdim  if (Mode == Normal) {
2124234353Sdim    if (isAllocated(RS, RSPrev, S)) {
2125234353Sdim      Msg = "Memory is allocated";
2126234353Sdim      StackHint = new StackHintGeneratorForSymbol(Sym,
2127234353Sdim                                                  "Returned allocated memory");
2128234353Sdim    } else if (isReleased(RS, RSPrev, S)) {
2129234353Sdim      Msg = "Memory is released";
2130234353Sdim      StackHint = new StackHintGeneratorForSymbol(Sym,
2131251662Sdim                                             "Returning; memory was released");
2132239462Sdim    } else if (isRelinquished(RS, RSPrev, S)) {
2133239462Sdim      Msg = "Memory ownership is transfered";
2134239462Sdim      StackHint = new StackHintGeneratorForSymbol(Sym, "");
2135234353Sdim    } else if (isReallocFailedCheck(RS, RSPrev, S)) {
2136234353Sdim      Mode = ReallocationFailed;
2137234353Sdim      Msg = "Reallocation failed";
2138234353Sdim      StackHint = new StackHintGeneratorForReallocationFailed(Sym,
2139234353Sdim                                                       "Reallocation failed");
2140234353Sdim
2141234353Sdim      if (SymbolRef sym = findFailedReallocSymbol(state, statePrev)) {
2142234353Sdim        // Is it possible to fail two reallocs WITHOUT testing in between?
2143234353Sdim        assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
2144234353Sdim          "We only support one failed realloc at a time.");
2145234353Sdim        BR.markInteresting(sym);
2146234353Sdim        FailedReallocSymbol = sym;
2147234353Sdim      }
2148234353Sdim    }
2149234353Sdim
2150234353Sdim  // We are in a special mode if a reallocation failed later in the path.
2151234353Sdim  } else if (Mode == ReallocationFailed) {
2152234353Sdim    assert(FailedReallocSymbol && "No symbol to look for.");
2153234353Sdim
2154234353Sdim    // Is this is the first appearance of the reallocated symbol?
2155234353Sdim    if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
2156234353Sdim      // We're at the reallocation point.
2157234353Sdim      Msg = "Attempt to reallocate memory";
2158234353Sdim      StackHint = new StackHintGeneratorForSymbol(Sym,
2159234353Sdim                                                 "Returned reallocated memory");
2160234353Sdim      FailedReallocSymbol = NULL;
2161234353Sdim      Mode = Normal;
2162234353Sdim    }
2163234353Sdim  }
2164234353Sdim
2165234353Sdim  if (!Msg)
2166234353Sdim    return 0;
2167234353Sdim  assert(StackHint);
2168234353Sdim
2169234353Sdim  // Generate the extra diagnostic.
2170234353Sdim  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
2171234353Sdim                             N->getLocationContext());
2172234353Sdim  return new PathDiagnosticEventPiece(Pos, Msg, true, StackHint);
2173234353Sdim}
2174234353Sdim
2175239462Sdimvoid MallocChecker::printState(raw_ostream &Out, ProgramStateRef State,
2176239462Sdim                               const char *NL, const char *Sep) const {
2177234353Sdim
2178239462Sdim  RegionStateTy RS = State->get<RegionState>();
2179239462Sdim
2180249423Sdim  if (!RS.isEmpty()) {
2181249423Sdim    Out << Sep << "MallocChecker:" << NL;
2182249423Sdim    for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
2183249423Sdim      I.getKey()->dumpToStream(Out);
2184249423Sdim      Out << " : ";
2185249423Sdim      I.getData().dump(Out);
2186249423Sdim      Out << NL;
2187249423Sdim    }
2188249423Sdim  }
2189239462Sdim}
2190239462Sdim
2191251662Sdimvoid ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
2192251662Sdim  registerCStringCheckerBasic(mgr);
2193251662Sdim  mgr.registerChecker<MallocChecker>()->Filter.CNewDeleteLeaksChecker = true;
2194251662Sdim  // We currently treat NewDeleteLeaks checker as a subchecker of NewDelete
2195251662Sdim  // checker.
2196251662Sdim  mgr.registerChecker<MallocChecker>()->Filter.CNewDeleteChecker = true;
2197251662Sdim}
2198251662Sdim
2199234353Sdim#define REGISTER_CHECKER(name) \
2200234353Sdimvoid ento::register##name(CheckerManager &mgr) {\
2201234353Sdim  registerCStringCheckerBasic(mgr); \
2202234353Sdim  mgr.registerChecker<MallocChecker>()->Filter.C##name = true;\
2203234353Sdim}
2204234353Sdim
2205234353SdimREGISTER_CHECKER(MallocPessimistic)
2206234353SdimREGISTER_CHECKER(MallocOptimistic)
2207249423SdimREGISTER_CHECKER(NewDeleteChecker)
2208249423SdimREGISTER_CHECKER(MismatchedDeallocatorChecker)
2209