MallocChecker.cpp revision 5251abea41b446c26e3239c8dd6c7edea6fc335d
1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//=== MallocChecker.cpp - A malloc/free checker -------------------*- C++ -*--//
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//                     The LLVM Compiler Infrastructure
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// This file is distributed under the University of Illinois Open Source
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// License. See LICENSE.TXT for details.
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//===----------------------------------------------------------------------===//
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// This file defines malloc/free checker, which checks for potential memory
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// leaks, double free, and use-after-free problems.
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org//===----------------------------------------------------------------------===//
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ClangSACheckers.h"
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "InterCheckerAPI.h"
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "clang/AST/Attr.h"
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "clang/Basic/SourceManager.h"
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "clang/StaticAnalyzer/Core/Checker.h"
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "clang/StaticAnalyzer/Core/CheckerManager.h"
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/ADT/ImmutableMap.h"
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/ADT/STLExtras.h"
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/ADT/SmallString.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "llvm/ADT/StringExtras.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <climits>
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgusing namespace clang;
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgusing namespace ento;
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace {
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass RefState {
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  enum Kind { // Reference to allocated memory.
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              Allocated,
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              // Reference to released/freed memory.
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              Released,
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              // The responsibility for freeing resources has transfered from
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              // this reference. A relinquished symbol should not be freed.
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              Relinquished } K;
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  const Stmt *S;
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  RefState(Kind k, const Stmt *s) : K(k), S(s) {}
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool isAllocated() const { return K == Allocated; }
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool isReleased() const { return K == Released; }
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool isRelinquished() const { return K == Relinquished; }
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  const Stmt *getStmt() const { return S; }
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool operator==(const RefState &X) const {
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return K == X.K && S == X.S;
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  static RefState getAllocated(const Stmt *s) {
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return RefState(Allocated, s);
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  static RefState getReleased(const Stmt *s) { return RefState(Released, s); }
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  static RefState getRelinquished(const Stmt *s) {
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return RefState(Relinquished, s);
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void Profile(llvm::FoldingSetNodeID &ID) const {
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ID.AddInteger(K);
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ID.AddPointer(S);
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void dump(raw_ostream &OS) const {
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    static const char *Table[] = {
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      "Allocated",
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      "Released",
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      "Relinquished"
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    };
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    OS << Table[(unsigned) K];
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  LLVM_ATTRIBUTE_USED void dump() const {
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    dump(llvm::errs());
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgenum ReallocPairKind {
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  RPToBeFreedAfterFailure,
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // The symbol has been freed when reallocation failed.
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  RPIsFreeOnFailure,
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // The symbol does not need to be freed after reallocation fails.
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  RPDoNotTrackAfterFailure
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// \class ReallocPair
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// \brief Stores information about the symbol being reallocated by a call to
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/// 'realloc' to allow modeling failed reallocation later in the path.
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct ReallocPair {
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // \brief The symbol which realloc reallocated.
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  SymbolRef ReallocatedSym;
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ReallocPairKind Kind;
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ReallocPair(SymbolRef S, ReallocPairKind K) :
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ReallocatedSym(S), Kind(K) {}
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void Profile(llvm::FoldingSetNodeID &ID) const {
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ID.AddInteger(Kind);
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ID.AddPointer(ReallocatedSym);
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool operator==(const ReallocPair &X) const {
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return ReallocatedSym == X.ReallocatedSym &&
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           Kind == X.Kind;
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtypedef std::pair<const ExplodedNode*, const MemRegion*> LeakInfo;
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass MallocChecker : public Checker<check::DeadSymbols,
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     check::PointerEscape,
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     check::PreStmt<ReturnStmt>,
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     check::PreStmt<CallExpr>,
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     check::PostStmt<CallExpr>,
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     check::PostStmt<BlockExpr>,
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     check::PostObjCMessage,
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     check::Location,
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     eval::Assume>
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mutable OwningPtr<BugType> BT_DoubleFree;
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mutable OwningPtr<BugType> BT_Leak;
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mutable OwningPtr<BugType> BT_UseFree;
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mutable OwningPtr<BugType> BT_BadFree;
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mutable OwningPtr<BugType> BT_OffsetFree;
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc,
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         *II_valloc, *II_reallocf, *II_strndup, *II_strdup;
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  MallocChecker() : II_malloc(0), II_free(0), II_realloc(0), II_calloc(0),
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    II_valloc(0), II_reallocf(0), II_strndup(0), II_strdup(0) {}
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// In pessimistic mode, the checker assumes that it does not know which
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// functions might free the memory.
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  struct ChecksFilter {
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    DefaultBool CMallocPessimistic;
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    DefaultBool CMallocOptimistic;
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  };
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ChecksFilter Filter;
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void checkPreStmt(const CallExpr *S, CheckerContext &C) const;
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void checkPostObjCMessage(const ObjCMethodCall &Call, CheckerContext &C) const;
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            bool Assumption) const;
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void checkLocation(SVal l, bool isLoad, const Stmt *S,
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     CheckerContext &C) const;
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ProgramStateRef checkPointerEscape(ProgramStateRef State,
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    const InvalidatedSymbols &Escaped,
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    const CallEvent *Call,
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    PointerEscapeKind Kind) const;
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void printState(raw_ostream &Out, ProgramStateRef State,
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  const char *NL, const char *Sep) const;
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprivate:
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void initIdentifierInfo(ASTContext &C) const;
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// Check if this is one of the functions which can allocate/reallocate memory
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// pointed to by one of its arguments.
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool isMemFunction(const FunctionDecl *FD, ASTContext &C) const;
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool isFreeFunction(const FunctionDecl *FD, ASTContext &C) const;
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool isAllocationFunction(const FunctionDecl *FD, ASTContext &C) const;
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  static ProgramStateRef MallocMemReturnsAttr(CheckerContext &C,
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                              const CallExpr *CE,
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                              const OwnershipAttr* Att);
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     const Expr *SizeEx, SVal Init,
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     ProgramStateRef state) {
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return MallocMemAux(C, CE,
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        state->getSVal(SizeEx, C.getLocationContext()),
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        Init, state);
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     SVal SizeEx, SVal Init,
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     ProgramStateRef state);
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// Update the RefState to reflect the new memory allocation.
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  static ProgramStateRef MallocUpdateRefState(CheckerContext &C,
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                              const CallExpr *CE,
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                              ProgramStateRef state);
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ProgramStateRef FreeMemAttr(CheckerContext &C, const CallExpr *CE,
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                              const OwnershipAttr* Att) const;
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ProgramStateRef FreeMemAux(CheckerContext &C, const CallExpr *CE,
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             ProgramStateRef state, unsigned Num,
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             bool Hold,
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             bool &ReleasedAllocated,
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             bool ReturnsNullOnFailure = false) const;
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ProgramStateRef FreeMemAux(CheckerContext &C, const Expr *Arg,
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             const Expr *ParentExpr,
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             ProgramStateRef State,
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             bool Hold,
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             bool &ReleasedAllocated,
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             bool ReturnsNullOnFailure = false) const;
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ProgramStateRef ReallocMem(CheckerContext &C, const CallExpr *CE,
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             bool FreesMemOnFailure) const;
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  static ProgramStateRef CallocMem(CheckerContext &C, const CallExpr *CE);
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ///\brief Check if the memory associated with this symbol was released.
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool isReleased(SymbolRef Sym, CheckerContext &C) const;
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         const Stmt *S = 0) const;
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// Check if the function is not known to us. So, for example, we could
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// conservatively assume it can free/reallocate it's pointer arguments.
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool doesNotFreeMemory(const CallEvent *Call,
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         ProgramStateRef State) const;
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  static bool SummarizeValue(raw_ostream &os, SVal V);
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range) const;
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range)const;
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// Find the location of the allocation for Sym on the path leading to the
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// exploded node N.
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                             CheckerContext &C) const;
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  void reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const;
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// The bug visitor which allows us to print extra diagnostics along the
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// BugReport path. For example, showing the allocation site of the leaked
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  /// region.
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  class MallocBugVisitor : public BugReporterVisitorImpl<MallocBugVisitor> {
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  protected:
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    enum NotificationMode {
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      Normal,
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ReallocationFailed
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    };
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    // The allocated region symbol tracked by the main analysis.
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    SymbolRef Sym;
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    // The mode we are in, i.e. what kind of diagnostics will be emitted.
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    NotificationMode Mode;
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    // A symbol from when the primary region should have been reallocated.
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    SymbolRef FailedReallocSymbol;
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    bool IsLeak;
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  public:
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    MallocBugVisitor(SymbolRef S, bool isLeak = false)
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       : Sym(S), Mode(Normal), FailedReallocSymbol(0), IsLeak(isLeak) {}
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    virtual ~MallocBugVisitor() {}
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    void Profile(llvm::FoldingSetNodeID &ID) const {
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      static int X = 0;
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ID.AddPointer(&X);
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ID.AddPointer(Sym);
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    inline bool isAllocated(const RefState *S, const RefState *SPrev,
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            const Stmt *Stmt) {
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // Did not track -> allocated. Other state (released) -> allocated.
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return (Stmt && isa<CallExpr>(Stmt) &&
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              (S && S->isAllocated()) && (!SPrev || !SPrev->isAllocated()));
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    inline bool isReleased(const RefState *S, const RefState *SPrev,
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           const Stmt *Stmt) {
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // Did not track -> released. Other state (allocated) -> released.
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return (Stmt && isa<CallExpr>(Stmt) &&
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              (S && S->isReleased()) && (!SPrev || !SPrev->isReleased()));
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    inline bool isRelinquished(const RefState *S, const RefState *SPrev,
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               const Stmt *Stmt) {
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // Did not track -> relinquished. Other state (allocated) -> relinquished.
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return (Stmt && (isa<CallExpr>(Stmt) || isa<ObjCMessageExpr>(Stmt) ||
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                              isa<ObjCPropertyRefExpr>(Stmt)) &&
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              (S && S->isRelinquished()) &&
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              (!SPrev || !SPrev->isRelinquished()));
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    inline bool isReallocFailedCheck(const RefState *S, const RefState *SPrev,
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     const Stmt *Stmt) {
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // If the expression is not a call, and the state change is
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // released -> allocated, it must be the realloc return value
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // check. If we have to handle more cases here, it might be cleaner just
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // to track this extra bit in the state itself.
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return ((!Stmt || !isa<CallExpr>(Stmt)) &&
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              (S && S->isAllocated()) && (SPrev && !SPrev->isAllocated()));
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   const ExplodedNode *PrevN,
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   BugReporterContext &BRC,
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                   BugReport &BR);
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    PathDiagnosticPiece* getEndPath(BugReporterContext &BRC,
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    const ExplodedNode *EndPathNode,
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                    BugReport &BR) {
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!IsLeak)
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return 0;
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      PathDiagnosticLocation L =
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        PathDiagnosticLocation::createEndOfPath(EndPathNode,
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                BRC.getSourceManager());
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      // Do not add the statement itself as a range in case of leak.
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return new PathDiagnosticEventPiece(L, BR.getDescription(), false);
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  private:
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    class StackHintGeneratorForReallocationFailed
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        : public StackHintGeneratorForSymbol {
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    public:
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      StackHintGeneratorForReallocationFailed(SymbolRef S, StringRef M)
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        : StackHintGeneratorForSymbol(S, M) {}
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex) {
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        // Printed parameters start at 1, not 0.
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        ++ArgIndex;
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        SmallString<200> buf;
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        llvm::raw_svector_ostream os(buf);
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        os << "Reallocation of " << ArgIndex << llvm::getOrdinalSuffix(ArgIndex)
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           << " parameter failed";
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return os.str();
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return "Reallocation of returned value failed";
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    };
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  };
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} // end anonymous namespace
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgREGISTER_MAP_WITH_PROGRAMSTATE(RegionState, SymbolRef, RefState)
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgREGISTER_MAP_WITH_PROGRAMSTATE(ReallocPairs, SymbolRef, ReallocPair)
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// A map from the freed symbol to the symbol representing the return value of
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// the free function.
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgREGISTER_MAP_WITH_PROGRAMSTATE(FreeReturnValue, SymbolRef, SymbolRef)
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace {
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass StopTrackingCallback : public SymbolVisitor {
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ProgramStateRef state;
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  StopTrackingCallback(ProgramStateRef st) : state(st) {}
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ProgramStateRef getState() const { return state; }
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool VisitSymbol(SymbolRef sym) {
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    state = state->remove<RegionState>(sym);
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return true;
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} // end anonymous namespace
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid MallocChecker::initIdentifierInfo(ASTContext &Ctx) const {
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (II_malloc)
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return;
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  II_malloc = &Ctx.Idents.get("malloc");
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  II_free = &Ctx.Idents.get("free");
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  II_realloc = &Ctx.Idents.get("realloc");
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  II_reallocf = &Ctx.Idents.get("reallocf");
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  II_calloc = &Ctx.Idents.get("calloc");
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  II_valloc = &Ctx.Idents.get("valloc");
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  II_strdup = &Ctx.Idents.get("strdup");
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  II_strndup = &Ctx.Idents.get("strndup");
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (isFreeFunction(FD, C))
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return true;
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (isAllocationFunction(FD, C))
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return true;
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return false;
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool MallocChecker::isAllocationFunction(const FunctionDecl *FD,
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         ASTContext &C) const {
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!FD)
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return false;
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (FD->getKind() == Decl::Function) {
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    IdentifierInfo *FunI = FD->getIdentifier();
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    initIdentifierInfo(C);
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (FunI == II_malloc || FunI == II_realloc ||
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        FunI == II_reallocf || FunI == II_calloc || FunI == II_valloc ||
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        FunI == II_strdup || FunI == II_strndup)
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return true;
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (Filter.CMallocOptimistic && FD->hasAttrs())
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for (specific_attr_iterator<OwnershipAttr>
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           i = FD->specific_attr_begin<OwnershipAttr>(),
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           e = FD->specific_attr_end<OwnershipAttr>();
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           i != e; ++i)
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((*i)->getOwnKind() == OwnershipAttr::Returns)
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return true;
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return false;
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool MallocChecker::isFreeFunction(const FunctionDecl *FD, ASTContext &C) const {
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!FD)
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return false;
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (FD->getKind() == Decl::Function) {
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    IdentifierInfo *FunI = FD->getIdentifier();
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    initIdentifierInfo(C);
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf)
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return true;
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (Filter.CMallocOptimistic && FD->hasAttrs())
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for (specific_attr_iterator<OwnershipAttr>
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           i = FD->specific_attr_begin<OwnershipAttr>(),
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           e = FD->specific_attr_end<OwnershipAttr>();
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org           i != e; ++i)
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((*i)->getOwnKind() == OwnershipAttr::Takes ||
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          (*i)->getOwnKind() == OwnershipAttr::Holds)
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return true;
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return false;
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const {
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (C.wasInlined)
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return;
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  const FunctionDecl *FD = C.getCalleeDecl(CE);
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!FD)
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return;
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  ProgramStateRef State = C.getState();
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool ReleasedAllocatedMemory = false;
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (FD->getKind() == Decl::Function) {
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    initIdentifierInfo(C.getASTContext());
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    IdentifierInfo *FunI = FD->getIdentifier();
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (FunI == II_malloc || FunI == II_valloc) {
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (CE->getNumArgs() < 1)
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return;
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else if (FunI == II_realloc) {
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      State = ReallocMem(C, CE, false);
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else if (FunI == II_reallocf) {
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      State = ReallocMem(C, CE, true);
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else if (FunI == II_calloc) {
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      State = CallocMem(C, CE);
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else if (FunI == II_free) {
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else if (FunI == II_strdup) {
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      State = MallocUpdateRefState(C, CE, State);
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    } else if (FunI == II_strndup) {
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      State = MallocUpdateRefState(C, CE, State);
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    }
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (Filter.CMallocOptimistic) {
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    // Check all the attributes, if there are any.
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    // There can be multiple of these attributes.
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (FD->hasAttrs())
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (specific_attr_iterator<OwnershipAttr>
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          i = FD->specific_attr_begin<OwnershipAttr>(),
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          e = FD->specific_attr_end<OwnershipAttr>();
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          i != e; ++i) {
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        switch ((*i)->getOwnKind()) {
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        case OwnershipAttr::Returns:
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          State = MallocMemReturnsAttr(C, CE, *i);
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          break;
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        case OwnershipAttr::Takes:
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        case OwnershipAttr::Holds:
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          State = FreeMemAttr(C, CE, *i);
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          break;
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        }
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  C.addTransition(State);
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool isFreeWhenDoneSetToZero(const ObjCMethodCall &Call) {
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  Selector S = Call.getSelector();
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  for (unsigned i = 1; i < S.getNumArgs(); ++i)
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if (S.getNameForSlot(i).equals("freeWhenDone"))
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (Call.getArgSVal(i).isConstant(0))
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return true;
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return false;
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid MallocChecker::checkPostObjCMessage(const ObjCMethodCall &Call,
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                         CheckerContext &C) const {
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (C.wasInlined)
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return;
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // If the first selector is dataWithBytesNoCopy, assume that the memory will
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // be released with 'free' by the new object.
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Ex:  [NSData dataWithBytesNoCopy:bytes length:10];
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Unless 'freeWhenDone' param set to 0.
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // TODO: Check that the memory was allocated with malloc.
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  bool ReleasedAllocatedMemory = false;
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  Selector S = Call.getSelector();
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if ((S.getNameForSlot(0) == "dataWithBytesNoCopy" ||
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       S.getNameForSlot(0) == "initWithBytesNoCopy" ||
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       S.getNameForSlot(0) == "initWithCharactersNoCopy") &&
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      !isFreeWhenDoneSetToZero(Call)){
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    unsigned int argIdx  = 0;
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    ProgramStateRef State = FreeMemAux(C, Call.getArgExpr(argIdx),
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       Call.getOriginExpr(), C.getState(), true,
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       ReleasedAllocatedMemory,
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       /* RetNullOnFailure*/ true);
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    C.addTransition(State);
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgProgramStateRef MallocChecker::MallocMemReturnsAttr(CheckerContext &C,
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                    const CallExpr *CE,
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                    const OwnershipAttr* Att) {
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (Att->getModule() != "malloc")
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return 0;
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (I != E) {
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), C.getState());
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                           const CallExpr *CE,
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                           SVal Size, SVal Init,
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                           ProgramStateRef state) {
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Bind the return value to the symbolic value from the heap region.
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // TODO: We could rewrite post visit to eval call; 'malloc' does not have
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // side effects other than what we model here.
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  unsigned Count = C.blockCount();
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  SValBuilder &svalBuilder = C.getSValBuilder();
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  DefinedSVal RetVal = svalBuilder.getConjuredHeapSymbolVal(CE, LCtx, Count)
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      .castAs<DefinedSVal>();
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  state = state->BindExpr(CE, C.getLocationContext(), RetVal);
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // We expect the malloc functions to return a pointer.
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!RetVal.getAs<Loc>())
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return 0;
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Fill the region with the initialization value.
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  state = state->bindDefault(RetVal, Init);
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Set the region's extent equal to the Size parameter.
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  const SymbolicRegion *R =
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      dyn_cast_or_null<SymbolicRegion>(RetVal.getAsRegion());
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!R)
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return 0;
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (llvm::Optional<DefinedOrUnknownSVal> DefinedSize =
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          Size.getAs<DefinedOrUnknownSVal>()) {
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    SValBuilder &svalBuilder = C.getSValBuilder();
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    DefinedOrUnknownSVal extentMatchesSize =
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        svalBuilder.evalEQ(state, Extent, *DefinedSize);
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    state = state->assume(extentMatchesSize, true);
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    assert(state);
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  }
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return MallocUpdateRefState(C, CE, state);
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgProgramStateRef MallocChecker::MallocUpdateRefState(CheckerContext &C,
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                    const CallExpr *CE,
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                    ProgramStateRef state) {
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Get the return value.
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  SVal retVal = state->getSVal(CE, C.getLocationContext());
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // We expect the malloc functions to return a pointer.
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  if (!retVal.getAs<Loc>())
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return 0;
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  SymbolRef Sym = retVal.getAsLocSymbol();
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  assert(Sym);
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  // Set the symbol's state to Allocated.
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org  return state->set<RegionState>(Sym, RefState::getAllocated(CE));
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgProgramStateRef MallocChecker::FreeMemAttr(CheckerContext &C,
607                                           const CallExpr *CE,
608                                           const OwnershipAttr* Att) const {
609  if (Att->getModule() != "malloc")
610    return 0;
611
612  ProgramStateRef State = C.getState();
613  bool ReleasedAllocated = false;
614
615  for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
616       I != E; ++I) {
617    ProgramStateRef StateI = FreeMemAux(C, CE, State, *I,
618                               Att->getOwnKind() == OwnershipAttr::Holds,
619                               ReleasedAllocated);
620    if (StateI)
621      State = StateI;
622  }
623  return State;
624}
625
626ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
627                                          const CallExpr *CE,
628                                          ProgramStateRef state,
629                                          unsigned Num,
630                                          bool Hold,
631                                          bool &ReleasedAllocated,
632                                          bool ReturnsNullOnFailure) const {
633  if (CE->getNumArgs() < (Num + 1))
634    return 0;
635
636  return FreeMemAux(C, CE->getArg(Num), CE, state, Hold,
637                    ReleasedAllocated, ReturnsNullOnFailure);
638}
639
640/// Checks if the previous call to free on the given symbol failed - if free
641/// failed, returns true. Also, returns the corresponding return value symbol.
642static bool didPreviousFreeFail(ProgramStateRef State,
643                                SymbolRef Sym, SymbolRef &RetStatusSymbol) {
644  const SymbolRef *Ret = State->get<FreeReturnValue>(Sym);
645  if (Ret) {
646    assert(*Ret && "We should not store the null return symbol");
647    ConstraintManager &CMgr = State->getConstraintManager();
648    ConditionTruthVal FreeFailed = CMgr.isNull(State, *Ret);
649    RetStatusSymbol = *Ret;
650    return FreeFailed.isConstrainedTrue();
651  }
652  return false;
653}
654
655ProgramStateRef MallocChecker::FreeMemAux(CheckerContext &C,
656                                          const Expr *ArgExpr,
657                                          const Expr *ParentExpr,
658                                          ProgramStateRef State,
659                                          bool Hold,
660                                          bool &ReleasedAllocated,
661                                          bool ReturnsNullOnFailure) const {
662
663  SVal ArgVal = State->getSVal(ArgExpr, C.getLocationContext());
664  if (!ArgVal.getAs<DefinedOrUnknownSVal>())
665    return 0;
666  DefinedOrUnknownSVal location = ArgVal.castAs<DefinedOrUnknownSVal>();
667
668  // Check for null dereferences.
669  if (!location.getAs<Loc>())
670    return 0;
671
672  // The explicit NULL case, no operation is performed.
673  ProgramStateRef notNullState, nullState;
674  llvm::tie(notNullState, nullState) = State->assume(location);
675  if (nullState && !notNullState)
676    return 0;
677
678  // Unknown values could easily be okay
679  // Undefined values are handled elsewhere
680  if (ArgVal.isUnknownOrUndef())
681    return 0;
682
683  const MemRegion *R = ArgVal.getAsRegion();
684
685  // Nonlocs can't be freed, of course.
686  // Non-region locations (labels and fixed addresses) also shouldn't be freed.
687  if (!R) {
688    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
689    return 0;
690  }
691
692  R = R->StripCasts();
693
694  // Blocks might show up as heap data, but should not be free()d
695  if (isa<BlockDataRegion>(R)) {
696    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
697    return 0;
698  }
699
700  const MemSpaceRegion *MS = R->getMemorySpace();
701
702  // Parameters, locals, statics, and globals shouldn't be freed.
703  if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
704    // FIXME: at the time this code was written, malloc() regions were
705    // represented by conjured symbols, which are all in UnknownSpaceRegion.
706    // This means that there isn't actually anything from HeapSpaceRegion
707    // that should be freed, even though we allow it here.
708    // Of course, free() can work on memory allocated outside the current
709    // function, so UnknownSpaceRegion is always a possibility.
710    // False negatives are better than false positives.
711
712    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
713    return 0;
714  }
715
716  const SymbolicRegion *SrBase = dyn_cast<SymbolicRegion>(R->getBaseRegion());
717  // Various cases could lead to non-symbol values here.
718  // For now, ignore them.
719  if (!SrBase)
720    return 0;
721
722  SymbolRef SymBase = SrBase->getSymbol();
723  const RefState *RsBase = State->get<RegionState>(SymBase);
724  SymbolRef PreviousRetStatusSymbol = 0;
725
726  // Check double free.
727  if (RsBase &&
728      (RsBase->isReleased() || RsBase->isRelinquished()) &&
729      !didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {
730
731    if (ExplodedNode *N = C.generateSink()) {
732      if (!BT_DoubleFree)
733        BT_DoubleFree.reset(
734          new BugType("Double free", "Memory Error"));
735      BugReport *R = new BugReport(*BT_DoubleFree,
736        (RsBase->isReleased() ? "Attempt to free released memory"
737                              : "Attempt to free non-owned memory"),
738        N);
739      R->addRange(ArgExpr->getSourceRange());
740      R->markInteresting(SymBase);
741      if (PreviousRetStatusSymbol)
742        R->markInteresting(PreviousRetStatusSymbol);
743      R->addVisitor(new MallocBugVisitor(SymBase));
744      C.emitReport(R);
745    }
746    return 0;
747  }
748
749  // Check if the memory location being freed is the actual location
750  // allocated, or an offset.
751  RegionOffset Offset = R->getAsOffset();
752  if (RsBase && RsBase->isAllocated() &&
753      Offset.isValid() &&
754      !Offset.hasSymbolicOffset() &&
755      Offset.getOffset() != 0) {
756    ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange());
757    return 0;
758  }
759
760  ReleasedAllocated = (RsBase != 0);
761
762  // Clean out the info on previous call to free return info.
763  State = State->remove<FreeReturnValue>(SymBase);
764
765  // Keep track of the return value. If it is NULL, we will know that free
766  // failed.
767  if (ReturnsNullOnFailure) {
768    SVal RetVal = C.getSVal(ParentExpr);
769    SymbolRef RetStatusSymbol = RetVal.getAsSymbol();
770    if (RetStatusSymbol) {
771      C.getSymbolManager().addSymbolDependency(SymBase, RetStatusSymbol);
772      State = State->set<FreeReturnValue>(SymBase, RetStatusSymbol);
773    }
774  }
775
776  // Normal free.
777  if (Hold) {
778    return State->set<RegionState>(SymBase,
779                                   RefState::getRelinquished(ParentExpr));
780  }
781  return State->set<RegionState>(SymBase, RefState::getReleased(ParentExpr));
782}
783
784bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
785  if (llvm::Optional<nonloc::ConcreteInt> IntVal =
786          V.getAs<nonloc::ConcreteInt>())
787    os << "an integer (" << IntVal->getValue() << ")";
788  else if (llvm::Optional<loc::ConcreteInt> ConstAddr =
789               V.getAs<loc::ConcreteInt>())
790    os << "a constant address (" << ConstAddr->getValue() << ")";
791  else if (llvm::Optional<loc::GotoLabel> Label = V.getAs<loc::GotoLabel>())
792    os << "the address of the label '" << Label->getLabel()->getName() << "'";
793  else
794    return false;
795
796  return true;
797}
798
799bool MallocChecker::SummarizeRegion(raw_ostream &os,
800                                    const MemRegion *MR) {
801  switch (MR->getKind()) {
802  case MemRegion::FunctionTextRegionKind: {
803    const NamedDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
804    if (FD)
805      os << "the address of the function '" << *FD << '\'';
806    else
807      os << "the address of a function";
808    return true;
809  }
810  case MemRegion::BlockTextRegionKind:
811    os << "block text";
812    return true;
813  case MemRegion::BlockDataRegionKind:
814    // FIXME: where the block came from?
815    os << "a block";
816    return true;
817  default: {
818    const MemSpaceRegion *MS = MR->getMemorySpace();
819
820    if (isa<StackLocalsSpaceRegion>(MS)) {
821      const VarRegion *VR = dyn_cast<VarRegion>(MR);
822      const VarDecl *VD;
823      if (VR)
824        VD = VR->getDecl();
825      else
826        VD = NULL;
827
828      if (VD)
829        os << "the address of the local variable '" << VD->getName() << "'";
830      else
831        os << "the address of a local stack variable";
832      return true;
833    }
834
835    if (isa<StackArgumentsSpaceRegion>(MS)) {
836      const VarRegion *VR = dyn_cast<VarRegion>(MR);
837      const VarDecl *VD;
838      if (VR)
839        VD = VR->getDecl();
840      else
841        VD = NULL;
842
843      if (VD)
844        os << "the address of the parameter '" << VD->getName() << "'";
845      else
846        os << "the address of a parameter";
847      return true;
848    }
849
850    if (isa<GlobalsSpaceRegion>(MS)) {
851      const VarRegion *VR = dyn_cast<VarRegion>(MR);
852      const VarDecl *VD;
853      if (VR)
854        VD = VR->getDecl();
855      else
856        VD = NULL;
857
858      if (VD) {
859        if (VD->isStaticLocal())
860          os << "the address of the static variable '" << VD->getName() << "'";
861        else
862          os << "the address of the global variable '" << VD->getName() << "'";
863      } else
864        os << "the address of a global variable";
865      return true;
866    }
867
868    return false;
869  }
870  }
871}
872
873void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
874                                  SourceRange range) const {
875  if (ExplodedNode *N = C.generateSink()) {
876    if (!BT_BadFree)
877      BT_BadFree.reset(new BugType("Bad free", "Memory Error"));
878
879    SmallString<100> buf;
880    llvm::raw_svector_ostream os(buf);
881
882    const MemRegion *MR = ArgVal.getAsRegion();
883    if (MR) {
884      while (const ElementRegion *ER = dyn_cast<ElementRegion>(MR))
885        MR = ER->getSuperRegion();
886
887      // Special case for alloca()
888      if (isa<AllocaRegion>(MR))
889        os << "Argument to free() was allocated by alloca(), not malloc()";
890      else {
891        os << "Argument to free() is ";
892        if (SummarizeRegion(os, MR))
893          os << ", which is not memory allocated by malloc()";
894        else
895          os << "not memory allocated by malloc()";
896      }
897    } else {
898      os << "Argument to free() is ";
899      if (SummarizeValue(os, ArgVal))
900        os << ", which is not memory allocated by malloc()";
901      else
902        os << "not memory allocated by malloc()";
903    }
904
905    BugReport *R = new BugReport(*BT_BadFree, os.str(), N);
906    R->markInteresting(MR);
907    R->addRange(range);
908    C.emitReport(R);
909  }
910}
911
912void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal,
913                                     SourceRange Range) const {
914  ExplodedNode *N = C.generateSink();
915  if (N == NULL)
916    return;
917
918  if (!BT_OffsetFree)
919    BT_OffsetFree.reset(new BugType("Offset free", "Memory Error"));
920
921  SmallString<100> buf;
922  llvm::raw_svector_ostream os(buf);
923
924  const MemRegion *MR = ArgVal.getAsRegion();
925  assert(MR && "Only MemRegion based symbols can have offset free errors");
926
927  RegionOffset Offset = MR->getAsOffset();
928  assert((Offset.isValid() &&
929          !Offset.hasSymbolicOffset() &&
930          Offset.getOffset() != 0) &&
931         "Only symbols with a valid offset can have offset free errors");
932
933  int offsetBytes = Offset.getOffset() / C.getASTContext().getCharWidth();
934
935  os << "Argument to free() is offset by "
936     << offsetBytes
937     << " "
938     << ((abs(offsetBytes) > 1) ? "bytes" : "byte")
939     << " from the start of memory allocated by malloc()";
940
941  BugReport *R = new BugReport(*BT_OffsetFree, os.str(), N);
942  R->markInteresting(MR->getBaseRegion());
943  R->addRange(Range);
944  C.emitReport(R);
945}
946
947ProgramStateRef MallocChecker::ReallocMem(CheckerContext &C,
948                                          const CallExpr *CE,
949                                          bool FreesOnFail) const {
950  if (CE->getNumArgs() < 2)
951    return 0;
952
953  ProgramStateRef state = C.getState();
954  const Expr *arg0Expr = CE->getArg(0);
955  const LocationContext *LCtx = C.getLocationContext();
956  SVal Arg0Val = state->getSVal(arg0Expr, LCtx);
957  if (!Arg0Val.getAs<DefinedOrUnknownSVal>())
958    return 0;
959  DefinedOrUnknownSVal arg0Val = Arg0Val.castAs<DefinedOrUnknownSVal>();
960
961  SValBuilder &svalBuilder = C.getSValBuilder();
962
963  DefinedOrUnknownSVal PtrEQ =
964    svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull());
965
966  // Get the size argument. If there is no size arg then give up.
967  const Expr *Arg1 = CE->getArg(1);
968  if (!Arg1)
969    return 0;
970
971  // Get the value of the size argument.
972  SVal Arg1ValG = state->getSVal(Arg1, LCtx);
973  if (!Arg1ValG.getAs<DefinedOrUnknownSVal>())
974    return 0;
975  DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs<DefinedOrUnknownSVal>();
976
977  // Compare the size argument to 0.
978  DefinedOrUnknownSVal SizeZero =
979    svalBuilder.evalEQ(state, Arg1Val,
980                       svalBuilder.makeIntValWithPtrWidth(0, false));
981
982  ProgramStateRef StatePtrIsNull, StatePtrNotNull;
983  llvm::tie(StatePtrIsNull, StatePtrNotNull) = state->assume(PtrEQ);
984  ProgramStateRef StateSizeIsZero, StateSizeNotZero;
985  llvm::tie(StateSizeIsZero, StateSizeNotZero) = state->assume(SizeZero);
986  // We only assume exceptional states if they are definitely true; if the
987  // state is under-constrained, assume regular realloc behavior.
988  bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
989  bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
990
991  // If the ptr is NULL and the size is not 0, the call is equivalent to
992  // malloc(size).
993  if ( PrtIsNull && !SizeIsZero) {
994    ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1),
995                                               UndefinedVal(), StatePtrIsNull);
996    return stateMalloc;
997  }
998
999  if (PrtIsNull && SizeIsZero)
1000    return 0;
1001
1002  // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
1003  assert(!PrtIsNull);
1004  SymbolRef FromPtr = arg0Val.getAsSymbol();
1005  SVal RetVal = state->getSVal(CE, LCtx);
1006  SymbolRef ToPtr = RetVal.getAsSymbol();
1007  if (!FromPtr || !ToPtr)
1008    return 0;
1009
1010  bool ReleasedAllocated = false;
1011
1012  // If the size is 0, free the memory.
1013  if (SizeIsZero)
1014    if (ProgramStateRef stateFree = FreeMemAux(C, CE, StateSizeIsZero, 0,
1015                                               false, ReleasedAllocated)){
1016      // The semantics of the return value are:
1017      // If size was equal to 0, either NULL or a pointer suitable to be passed
1018      // to free() is returned. We just free the input pointer and do not add
1019      // any constrains on the output pointer.
1020      return stateFree;
1021    }
1022
1023  // Default behavior.
1024  if (ProgramStateRef stateFree =
1025        FreeMemAux(C, CE, state, 0, false, ReleasedAllocated)) {
1026
1027    ProgramStateRef stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
1028                                                UnknownVal(), stateFree);
1029    if (!stateRealloc)
1030      return 0;
1031
1032    ReallocPairKind Kind = RPToBeFreedAfterFailure;
1033    if (FreesOnFail)
1034      Kind = RPIsFreeOnFailure;
1035    else if (!ReleasedAllocated)
1036      Kind = RPDoNotTrackAfterFailure;
1037
1038    // Record the info about the reallocated symbol so that we could properly
1039    // process failed reallocation.
1040    stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
1041                                                   ReallocPair(FromPtr, Kind));
1042    // The reallocated symbol should stay alive for as long as the new symbol.
1043    C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
1044    return stateRealloc;
1045  }
1046  return 0;
1047}
1048
1049ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){
1050  if (CE->getNumArgs() < 2)
1051    return 0;
1052
1053  ProgramStateRef state = C.getState();
1054  SValBuilder &svalBuilder = C.getSValBuilder();
1055  const LocationContext *LCtx = C.getLocationContext();
1056  SVal count = state->getSVal(CE->getArg(0), LCtx);
1057  SVal elementSize = state->getSVal(CE->getArg(1), LCtx);
1058  SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize,
1059                                        svalBuilder.getContext().getSizeType());
1060  SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
1061
1062  return MallocMemAux(C, CE, TotalSize, zeroVal, state);
1063}
1064
1065LeakInfo
1066MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym,
1067                                 CheckerContext &C) const {
1068  const LocationContext *LeakContext = N->getLocationContext();
1069  // Walk the ExplodedGraph backwards and find the first node that referred to
1070  // the tracked symbol.
1071  const ExplodedNode *AllocNode = N;
1072  const MemRegion *ReferenceRegion = 0;
1073
1074  while (N) {
1075    ProgramStateRef State = N->getState();
1076    if (!State->get<RegionState>(Sym))
1077      break;
1078
1079    // Find the most recent expression bound to the symbol in the current
1080    // context.
1081    if (!ReferenceRegion) {
1082      if (const MemRegion *MR = C.getLocationRegionIfPostStore(N)) {
1083        SVal Val = State->getSVal(MR);
1084        if (Val.getAsLocSymbol() == Sym)
1085          ReferenceRegion = MR;
1086      }
1087    }
1088
1089    // Allocation node, is the last node in the current context in which the
1090    // symbol was tracked.
1091    if (N->getLocationContext() == LeakContext)
1092      AllocNode = N;
1093    N = N->pred_empty() ? NULL : *(N->pred_begin());
1094  }
1095
1096  return LeakInfo(AllocNode, ReferenceRegion);
1097}
1098
1099void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
1100                               CheckerContext &C) const {
1101  assert(N);
1102  if (!BT_Leak) {
1103    BT_Leak.reset(new BugType("Memory leak", "Memory Error"));
1104    // Leaks should not be reported if they are post-dominated by a sink:
1105    // (1) Sinks are higher importance bugs.
1106    // (2) NoReturnFunctionChecker uses sink nodes to represent paths ending
1107    //     with __noreturn functions such as assert() or exit(). We choose not
1108    //     to report leaks on such paths.
1109    BT_Leak->setSuppressOnSink(true);
1110  }
1111
1112  // Most bug reports are cached at the location where they occurred.
1113  // With leaks, we want to unique them by the location where they were
1114  // allocated, and only report a single path.
1115  PathDiagnosticLocation LocUsedForUniqueing;
1116  const ExplodedNode *AllocNode = 0;
1117  const MemRegion *Region = 0;
1118  llvm::tie(AllocNode, Region) = getAllocationSite(N, Sym, C);
1119
1120  ProgramPoint P = AllocNode->getLocation();
1121  const Stmt *AllocationStmt = 0;
1122  if (CallExitEnd *Exit = dyn_cast<CallExitEnd>(&P))
1123    AllocationStmt = Exit->getCalleeContext()->getCallSite();
1124  else if (StmtPoint *SP = dyn_cast<StmtPoint>(&P))
1125    AllocationStmt = SP->getStmt();
1126  if (AllocationStmt)
1127    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt,
1128                                              C.getSourceManager(),
1129                                              AllocNode->getLocationContext());
1130
1131  SmallString<200> buf;
1132  llvm::raw_svector_ostream os(buf);
1133  os << "Memory is never released; potential leak";
1134  if (Region && Region->canPrintPretty()) {
1135    os << " of memory pointed to by '";
1136    Region->printPretty(os);
1137    os << '\'';
1138  }
1139
1140  BugReport *R = new BugReport(*BT_Leak, os.str(), N,
1141                               LocUsedForUniqueing,
1142                               AllocNode->getLocationContext()->getDecl());
1143  R->markInteresting(Sym);
1144  R->addVisitor(new MallocBugVisitor(Sym, true));
1145  C.emitReport(R);
1146}
1147
1148void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
1149                                     CheckerContext &C) const
1150{
1151  if (!SymReaper.hasDeadSymbols())
1152    return;
1153
1154  ProgramStateRef state = C.getState();
1155  RegionStateTy RS = state->get<RegionState>();
1156  RegionStateTy::Factory &F = state->get_context<RegionState>();
1157
1158  SmallVector<SymbolRef, 2> Errors;
1159  for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
1160    if (SymReaper.isDead(I->first)) {
1161      if (I->second.isAllocated())
1162        Errors.push_back(I->first);
1163      // Remove the dead symbol from the map.
1164      RS = F.remove(RS, I->first);
1165
1166    }
1167  }
1168
1169  // Cleanup the Realloc Pairs Map.
1170  ReallocPairsTy RP = state->get<ReallocPairs>();
1171  for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
1172    if (SymReaper.isDead(I->first) ||
1173        SymReaper.isDead(I->second.ReallocatedSym)) {
1174      state = state->remove<ReallocPairs>(I->first);
1175    }
1176  }
1177
1178  // Cleanup the FreeReturnValue Map.
1179  FreeReturnValueTy FR = state->get<FreeReturnValue>();
1180  for (FreeReturnValueTy::iterator I = FR.begin(), E = FR.end(); I != E; ++I) {
1181    if (SymReaper.isDead(I->first) ||
1182        SymReaper.isDead(I->second)) {
1183      state = state->remove<FreeReturnValue>(I->first);
1184    }
1185  }
1186
1187  // Generate leak node.
1188  ExplodedNode *N = C.getPredecessor();
1189  if (!Errors.empty()) {
1190    static SimpleProgramPointTag Tag("MallocChecker : DeadSymbolsLeak");
1191    N = C.addTransition(C.getState(), C.getPredecessor(), &Tag);
1192    for (SmallVector<SymbolRef, 2>::iterator
1193        I = Errors.begin(), E = Errors.end(); I != E; ++I) {
1194      reportLeak(*I, N, C);
1195    }
1196  }
1197
1198  C.addTransition(state->set<RegionState>(RS), N);
1199}
1200
1201void MallocChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const {
1202  // We will check for double free in the post visit.
1203  if (isFreeFunction(C.getCalleeDecl(CE), C.getASTContext()))
1204    return;
1205
1206  // Check use after free, when a freed pointer is passed to a call.
1207  ProgramStateRef State = C.getState();
1208  for (CallExpr::const_arg_iterator I = CE->arg_begin(),
1209                                    E = CE->arg_end(); I != E; ++I) {
1210    const Expr *A = *I;
1211    if (A->getType().getTypePtr()->isAnyPointerType()) {
1212      SymbolRef Sym = State->getSVal(A, C.getLocationContext()).getAsSymbol();
1213      if (!Sym)
1214        continue;
1215      if (checkUseAfterFree(Sym, C, A))
1216        return;
1217    }
1218  }
1219}
1220
1221void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
1222  const Expr *E = S->getRetValue();
1223  if (!E)
1224    return;
1225
1226  // Check if we are returning a symbol.
1227  ProgramStateRef State = C.getState();
1228  SVal RetVal = State->getSVal(E, C.getLocationContext());
1229  SymbolRef Sym = RetVal.getAsSymbol();
1230  if (!Sym)
1231    // If we are returning a field of the allocated struct or an array element,
1232    // the callee could still free the memory.
1233    // TODO: This logic should be a part of generic symbol escape callback.
1234    if (const MemRegion *MR = RetVal.getAsRegion())
1235      if (isa<FieldRegion>(MR) || isa<ElementRegion>(MR))
1236        if (const SymbolicRegion *BMR =
1237              dyn_cast<SymbolicRegion>(MR->getBaseRegion()))
1238          Sym = BMR->getSymbol();
1239
1240  // Check if we are returning freed memory.
1241  if (Sym)
1242    checkUseAfterFree(Sym, C, E);
1243}
1244
1245// TODO: Blocks should be either inlined or should call invalidate regions
1246// upon invocation. After that's in place, special casing here will not be
1247// needed.
1248void MallocChecker::checkPostStmt(const BlockExpr *BE,
1249                                  CheckerContext &C) const {
1250
1251  // Scan the BlockDecRefExprs for any object the retain count checker
1252  // may be tracking.
1253  if (!BE->getBlockDecl()->hasCaptures())
1254    return;
1255
1256  ProgramStateRef state = C.getState();
1257  const BlockDataRegion *R =
1258    cast<BlockDataRegion>(state->getSVal(BE,
1259                                         C.getLocationContext()).getAsRegion());
1260
1261  BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
1262                                            E = R->referenced_vars_end();
1263
1264  if (I == E)
1265    return;
1266
1267  SmallVector<const MemRegion*, 10> Regions;
1268  const LocationContext *LC = C.getLocationContext();
1269  MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
1270
1271  for ( ; I != E; ++I) {
1272    const VarRegion *VR = I.getCapturedRegion();
1273    if (VR->getSuperRegion() == R) {
1274      VR = MemMgr.getVarRegion(VR->getDecl(), LC);
1275    }
1276    Regions.push_back(VR);
1277  }
1278
1279  state =
1280    state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
1281                                    Regions.data() + Regions.size()).getState();
1282  C.addTransition(state);
1283}
1284
1285bool MallocChecker::isReleased(SymbolRef Sym, CheckerContext &C) const {
1286  assert(Sym);
1287  const RefState *RS = C.getState()->get<RegionState>(Sym);
1288  return (RS && RS->isReleased());
1289}
1290
1291bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C,
1292                                      const Stmt *S) const {
1293  if (isReleased(Sym, C)) {
1294    if (ExplodedNode *N = C.generateSink()) {
1295      if (!BT_UseFree)
1296        BT_UseFree.reset(new BugType("Use-after-free", "Memory Error"));
1297
1298      BugReport *R = new BugReport(*BT_UseFree,
1299                                   "Use of memory after it is freed",N);
1300      if (S)
1301        R->addRange(S->getSourceRange());
1302      R->markInteresting(Sym);
1303      R->addVisitor(new MallocBugVisitor(Sym));
1304      C.emitReport(R);
1305      return true;
1306    }
1307  }
1308  return false;
1309}
1310
1311// Check if the location is a freed symbolic region.
1312void MallocChecker::checkLocation(SVal l, bool isLoad, const Stmt *S,
1313                                  CheckerContext &C) const {
1314  SymbolRef Sym = l.getLocSymbolInBase();
1315  if (Sym)
1316    checkUseAfterFree(Sym, C, S);
1317}
1318
1319// If a symbolic region is assumed to NULL (or another constant), stop tracking
1320// it - assuming that allocation failed on this path.
1321ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state,
1322                                              SVal Cond,
1323                                              bool Assumption) const {
1324  RegionStateTy RS = state->get<RegionState>();
1325  for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
1326    // If the symbol is assumed to be NULL, remove it from consideration.
1327    ConstraintManager &CMgr = state->getConstraintManager();
1328    ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
1329    if (AllocFailed.isConstrainedTrue())
1330      state = state->remove<RegionState>(I.getKey());
1331  }
1332
1333  // Realloc returns 0 when reallocation fails, which means that we should
1334  // restore the state of the pointer being reallocated.
1335  ReallocPairsTy RP = state->get<ReallocPairs>();
1336  for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) {
1337    // If the symbol is assumed to be NULL, remove it from consideration.
1338    ConstraintManager &CMgr = state->getConstraintManager();
1339    ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey());
1340    if (!AllocFailed.isConstrainedTrue())
1341      continue;
1342
1343    SymbolRef ReallocSym = I.getData().ReallocatedSym;
1344    if (const RefState *RS = state->get<RegionState>(ReallocSym)) {
1345      if (RS->isReleased()) {
1346        if (I.getData().Kind == RPToBeFreedAfterFailure)
1347          state = state->set<RegionState>(ReallocSym,
1348              RefState::getAllocated(RS->getStmt()));
1349        else if (I.getData().Kind == RPDoNotTrackAfterFailure)
1350          state = state->remove<RegionState>(ReallocSym);
1351        else
1352          assert(I.getData().Kind == RPIsFreeOnFailure);
1353      }
1354    }
1355    state = state->remove<ReallocPairs>(I.getKey());
1356  }
1357
1358  return state;
1359}
1360
1361// Check if the function is known to us. So, for example, we could
1362// conservatively assume it can free/reallocate its pointer arguments.
1363// (We assume that the pointers cannot escape through calls to system
1364// functions not handled by this checker.)
1365bool MallocChecker::doesNotFreeMemory(const CallEvent *Call,
1366                                      ProgramStateRef State) const {
1367  assert(Call);
1368
1369  // For now, assume that any C++ call can free memory.
1370  // TODO: If we want to be more optimistic here, we'll need to make sure that
1371  // regions escape to C++ containers. They seem to do that even now, but for
1372  // mysterious reasons.
1373  if (!(isa<FunctionCall>(Call) || isa<ObjCMethodCall>(Call)))
1374    return false;
1375
1376  // Check Objective-C messages by selector name.
1377  if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) {
1378    // If it's not a framework call, or if it takes a callback, assume it
1379    // can free memory.
1380    if (!Call->isInSystemHeader() || Call->hasNonZeroCallbackArg())
1381      return false;
1382
1383    Selector S = Msg->getSelector();
1384
1385    // Whitelist the ObjC methods which do free memory.
1386    // - Anything containing 'freeWhenDone' param set to 1.
1387    //   Ex: dataWithBytesNoCopy:length:freeWhenDone.
1388    for (unsigned i = 1; i < S.getNumArgs(); ++i) {
1389      if (S.getNameForSlot(i).equals("freeWhenDone")) {
1390        if (Call->getArgSVal(i).isConstant(1))
1391          return false;
1392        else
1393          return true;
1394      }
1395    }
1396
1397    // If the first selector ends with NoCopy, assume that the ownership is
1398    // transferred as well.
1399    // Ex:  [NSData dataWithBytesNoCopy:bytes length:10];
1400    StringRef FirstSlot = S.getNameForSlot(0);
1401    if (FirstSlot.endswith("NoCopy"))
1402      return false;
1403
1404    // If the first selector starts with addPointer, insertPointer,
1405    // or replacePointer, assume we are dealing with NSPointerArray or similar.
1406    // This is similar to C++ containers (vector); we still might want to check
1407    // that the pointers get freed by following the container itself.
1408    if (FirstSlot.startswith("addPointer") ||
1409        FirstSlot.startswith("insertPointer") ||
1410        FirstSlot.startswith("replacePointer")) {
1411      return false;
1412    }
1413
1414    // Otherwise, assume that the method does not free memory.
1415    // Most framework methods do not free memory.
1416    return true;
1417  }
1418
1419  // At this point the only thing left to handle is straight function calls.
1420  const FunctionDecl *FD = cast<FunctionCall>(Call)->getDecl();
1421  if (!FD)
1422    return false;
1423
1424  ASTContext &ASTC = State->getStateManager().getContext();
1425
1426  // If it's one of the allocation functions we can reason about, we model
1427  // its behavior explicitly.
1428  if (isMemFunction(FD, ASTC))
1429    return true;
1430
1431  // If it's not a system call, assume it frees memory.
1432  if (!Call->isInSystemHeader())
1433    return false;
1434
1435  // White list the system functions whose arguments escape.
1436  const IdentifierInfo *II = FD->getIdentifier();
1437  if (!II)
1438    return false;
1439  StringRef FName = II->getName();
1440
1441  // White list the 'XXXNoCopy' CoreFoundation functions.
1442  // We specifically check these before
1443  if (FName.endswith("NoCopy")) {
1444    // Look for the deallocator argument. We know that the memory ownership
1445    // is not transferred only if the deallocator argument is
1446    // 'kCFAllocatorNull'.
1447    for (unsigned i = 1; i < Call->getNumArgs(); ++i) {
1448      const Expr *ArgE = Call->getArgExpr(i)->IgnoreParenCasts();
1449      if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(ArgE)) {
1450        StringRef DeallocatorName = DE->getFoundDecl()->getName();
1451        if (DeallocatorName == "kCFAllocatorNull")
1452          return true;
1453      }
1454    }
1455    return false;
1456  }
1457
1458  // Associating streams with malloced buffers. The pointer can escape if
1459  // 'closefn' is specified (and if that function does free memory),
1460  // but it will not if closefn is not specified.
1461  // Currently, we do not inspect the 'closefn' function (PR12101).
1462  if (FName == "funopen")
1463    if (Call->getNumArgs() >= 4 && Call->getArgSVal(4).isConstant(0))
1464      return true;
1465
1466  // Do not warn on pointers passed to 'setbuf' when used with std streams,
1467  // these leaks might be intentional when setting the buffer for stdio.
1468  // http://stackoverflow.com/questions/2671151/who-frees-setvbuf-buffer
1469  if (FName == "setbuf" || FName =="setbuffer" ||
1470      FName == "setlinebuf" || FName == "setvbuf") {
1471    if (Call->getNumArgs() >= 1) {
1472      const Expr *ArgE = Call->getArgExpr(0)->IgnoreParenCasts();
1473      if (const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE))
1474        if (const VarDecl *D = dyn_cast<VarDecl>(ArgDRE->getDecl()))
1475          if (D->getCanonicalDecl()->getName().find("std") != StringRef::npos)
1476            return false;
1477    }
1478  }
1479
1480  // A bunch of other functions which either take ownership of a pointer or
1481  // wrap the result up in a struct or object, meaning it can be freed later.
1482  // (See RetainCountChecker.) Not all the parameters here are invalidated,
1483  // but the Malloc checker cannot differentiate between them. The right way
1484  // of doing this would be to implement a pointer escapes callback.
1485  if (FName == "CGBitmapContextCreate" ||
1486      FName == "CGBitmapContextCreateWithData" ||
1487      FName == "CVPixelBufferCreateWithBytes" ||
1488      FName == "CVPixelBufferCreateWithPlanarBytes" ||
1489      FName == "OSAtomicEnqueue") {
1490    return false;
1491  }
1492
1493  // Handle cases where we know a buffer's /address/ can escape.
1494  // Note that the above checks handle some special cases where we know that
1495  // even though the address escapes, it's still our responsibility to free the
1496  // buffer.
1497  if (Call->argumentsMayEscape())
1498    return false;
1499
1500  // Otherwise, assume that the function does not free memory.
1501  // Most system calls do not free the memory.
1502  return true;
1503}
1504
1505ProgramStateRef MallocChecker::checkPointerEscape(ProgramStateRef State,
1506                                             const InvalidatedSymbols &Escaped,
1507                                             const CallEvent *Call,
1508                                             PointerEscapeKind Kind) const {
1509  // If we know that the call does not free memory, keep tracking the top
1510  // level arguments.
1511  if ((Kind == PSK_DirectEscapeOnCall ||
1512       Kind == PSK_IndirectEscapeOnCall) &&
1513      doesNotFreeMemory(Call, State)) {
1514    return State;
1515  }
1516
1517  for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
1518                                          E = Escaped.end();
1519                                          I != E; ++I) {
1520    SymbolRef sym = *I;
1521
1522    if (const RefState *RS = State->get<RegionState>(sym)) {
1523      if (RS->isAllocated())
1524        State = State->remove<RegionState>(sym);
1525    }
1526  }
1527  return State;
1528}
1529
1530static SymbolRef findFailedReallocSymbol(ProgramStateRef currState,
1531                                         ProgramStateRef prevState) {
1532  ReallocPairsTy currMap = currState->get<ReallocPairs>();
1533  ReallocPairsTy prevMap = prevState->get<ReallocPairs>();
1534
1535  for (ReallocPairsTy::iterator I = prevMap.begin(), E = prevMap.end();
1536       I != E; ++I) {
1537    SymbolRef sym = I.getKey();
1538    if (!currMap.lookup(sym))
1539      return sym;
1540  }
1541
1542  return NULL;
1543}
1544
1545PathDiagnosticPiece *
1546MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
1547                                           const ExplodedNode *PrevN,
1548                                           BugReporterContext &BRC,
1549                                           BugReport &BR) {
1550  ProgramStateRef state = N->getState();
1551  ProgramStateRef statePrev = PrevN->getState();
1552
1553  const RefState *RS = state->get<RegionState>(Sym);
1554  const RefState *RSPrev = statePrev->get<RegionState>(Sym);
1555  if (!RS)
1556    return 0;
1557
1558  const Stmt *S = 0;
1559  const char *Msg = 0;
1560  StackHintGeneratorForSymbol *StackHint = 0;
1561
1562  // Retrieve the associated statement.
1563  ProgramPoint ProgLoc = N->getLocation();
1564  if (StmtPoint *SP = dyn_cast<StmtPoint>(&ProgLoc)) {
1565    S = SP->getStmt();
1566  } else if (CallExitEnd *Exit = dyn_cast<CallExitEnd>(&ProgLoc)) {
1567    S = Exit->getCalleeContext()->getCallSite();
1568  } else if (BlockEdge *Edge = dyn_cast<BlockEdge>(&ProgLoc)) {
1569    // If an assumption was made on a branch, it should be caught
1570    // here by looking at the state transition.
1571    S = Edge->getSrc()->getTerminator();
1572  }
1573
1574  if (!S)
1575    return 0;
1576
1577  // FIXME: We will eventually need to handle non-statement-based events
1578  // (__attribute__((cleanup))).
1579
1580  // Find out if this is an interesting point and what is the kind.
1581  if (Mode == Normal) {
1582    if (isAllocated(RS, RSPrev, S)) {
1583      Msg = "Memory is allocated";
1584      StackHint = new StackHintGeneratorForSymbol(Sym,
1585                                                  "Returned allocated memory");
1586    } else if (isReleased(RS, RSPrev, S)) {
1587      Msg = "Memory is released";
1588      StackHint = new StackHintGeneratorForSymbol(Sym,
1589                                                  "Returned released memory");
1590    } else if (isRelinquished(RS, RSPrev, S)) {
1591      Msg = "Memory ownership is transfered";
1592      StackHint = new StackHintGeneratorForSymbol(Sym, "");
1593    } else if (isReallocFailedCheck(RS, RSPrev, S)) {
1594      Mode = ReallocationFailed;
1595      Msg = "Reallocation failed";
1596      StackHint = new StackHintGeneratorForReallocationFailed(Sym,
1597                                                       "Reallocation failed");
1598
1599      if (SymbolRef sym = findFailedReallocSymbol(state, statePrev)) {
1600        // Is it possible to fail two reallocs WITHOUT testing in between?
1601        assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
1602          "We only support one failed realloc at a time.");
1603        BR.markInteresting(sym);
1604        FailedReallocSymbol = sym;
1605      }
1606    }
1607
1608  // We are in a special mode if a reallocation failed later in the path.
1609  } else if (Mode == ReallocationFailed) {
1610    assert(FailedReallocSymbol && "No symbol to look for.");
1611
1612    // Is this is the first appearance of the reallocated symbol?
1613    if (!statePrev->get<RegionState>(FailedReallocSymbol)) {
1614      // We're at the reallocation point.
1615      Msg = "Attempt to reallocate memory";
1616      StackHint = new StackHintGeneratorForSymbol(Sym,
1617                                                 "Returned reallocated memory");
1618      FailedReallocSymbol = NULL;
1619      Mode = Normal;
1620    }
1621  }
1622
1623  if (!Msg)
1624    return 0;
1625  assert(StackHint);
1626
1627  // Generate the extra diagnostic.
1628  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
1629                             N->getLocationContext());
1630  return new PathDiagnosticEventPiece(Pos, Msg, true, StackHint);
1631}
1632
1633void MallocChecker::printState(raw_ostream &Out, ProgramStateRef State,
1634                               const char *NL, const char *Sep) const {
1635
1636  RegionStateTy RS = State->get<RegionState>();
1637
1638  if (!RS.isEmpty()) {
1639    Out << Sep << "MallocChecker:" << NL;
1640    for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
1641      I.getKey()->dumpToStream(Out);
1642      Out << " : ";
1643      I.getData().dump(Out);
1644      Out << NL;
1645    }
1646  }
1647}
1648
1649#define REGISTER_CHECKER(name) \
1650void ento::register##name(CheckerManager &mgr) {\
1651  registerCStringCheckerBasic(mgr); \
1652  mgr.registerChecker<MallocChecker>()->Filter.C##name = true;\
1653}
1654
1655REGISTER_CHECKER(MallocPessimistic)
1656REGISTER_CHECKER(MallocOptimistic)
1657