MallocChecker.cpp revision 6810630bb00ba2944cbeb54834f38f69dbddfd7f
1//=== MallocChecker.cpp - A malloc/free checker -------------------*- C++ -*--//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines malloc/free checker, which checks for potential memory
11// leaks, double free, and use-after-free problems.
12//
13//===----------------------------------------------------------------------===//
14
15#include "ExperimentalChecks.h"
16#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
17#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h"
18#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
21#include "llvm/ADT/ImmutableMap.h"
22using namespace clang;
23using namespace ento;
24
25namespace {
26
27class RefState {
28  enum Kind { AllocateUnchecked, AllocateFailed, Released, Escaped,
29              Relinquished } K;
30  const Stmt *S;
31
32public:
33  RefState(Kind k, const Stmt *s) : K(k), S(s) {}
34
35  bool isAllocated() const { return K == AllocateUnchecked; }
36  //bool isFailed() const { return K == AllocateFailed; }
37  bool isReleased() const { return K == Released; }
38  //bool isEscaped() const { return K == Escaped; }
39  //bool isRelinquished() const { return K == Relinquished; }
40
41  bool operator==(const RefState &X) const {
42    return K == X.K && S == X.S;
43  }
44
45  static RefState getAllocateUnchecked(const Stmt *s) {
46    return RefState(AllocateUnchecked, s);
47  }
48  static RefState getAllocateFailed() {
49    return RefState(AllocateFailed, 0);
50  }
51  static RefState getReleased(const Stmt *s) { return RefState(Released, s); }
52  static RefState getEscaped(const Stmt *s) { return RefState(Escaped, s); }
53  static RefState getRelinquished(const Stmt *s) {
54    return RefState(Relinquished, s);
55  }
56
57  void Profile(llvm::FoldingSetNodeID &ID) const {
58    ID.AddInteger(K);
59    ID.AddPointer(S);
60  }
61};
62
63class RegionState {};
64
65class MallocChecker : public CheckerVisitor<MallocChecker> {
66  BuiltinBug *BT_DoubleFree;
67  BuiltinBug *BT_Leak;
68  BuiltinBug *BT_UseFree;
69  BuiltinBug *BT_UseRelinquished;
70  BuiltinBug *BT_BadFree;
71  IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc;
72
73public:
74  MallocChecker()
75    : BT_DoubleFree(0), BT_Leak(0), BT_UseFree(0), BT_UseRelinquished(0),
76      BT_BadFree(0),
77      II_malloc(0), II_free(0), II_realloc(0), II_calloc(0) {}
78  static void *getTag();
79  bool evalCallExpr(CheckerContext &C, const CallExpr *CE);
80  void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper);
81  void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, ExprEngine &Eng);
82  void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
83  const GRState *evalAssume(const GRState *state, SVal Cond, bool Assumption,
84                            bool *respondsToCallback);
85  void visitLocation(CheckerContext &C, const Stmt *S, SVal l, bool isLoad);
86  virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
87                            SVal location, SVal val);
88
89private:
90  void MallocMem(CheckerContext &C, const CallExpr *CE);
91  void MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
92                            const OwnershipAttr* Att);
93  const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
94                              const Expr *SizeEx, SVal Init,
95                              const GRState *state) {
96    return MallocMemAux(C, CE, state->getSVal(SizeEx), Init, state);
97  }
98  const GRState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
99                              SVal SizeEx, SVal Init,
100                              const GRState *state);
101
102  void FreeMem(CheckerContext &C, const CallExpr *CE);
103  void FreeMemAttr(CheckerContext &C, const CallExpr *CE,
104                   const OwnershipAttr* Att);
105  const GRState *FreeMemAux(CheckerContext &C, const CallExpr *CE,
106                            const GRState *state, unsigned Num, bool Hold);
107
108  void ReallocMem(CheckerContext &C, const CallExpr *CE);
109  void CallocMem(CheckerContext &C, const CallExpr *CE);
110
111  bool SummarizeValue(llvm::raw_ostream& os, SVal V);
112  bool SummarizeRegion(llvm::raw_ostream& os, const MemRegion *MR);
113  void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange range);
114};
115} // end anonymous namespace
116
117typedef llvm::ImmutableMap<SymbolRef, RefState> RegionStateTy;
118
119namespace clang {
120namespace ento {
121  template <>
122  struct GRStateTrait<RegionState>
123    : public GRStatePartialTrait<RegionStateTy> {
124    static void *GDMIndex() { return MallocChecker::getTag(); }
125  };
126}
127}
128
129void ento::RegisterMallocChecker(ExprEngine &Eng) {
130  Eng.registerCheck(new MallocChecker());
131}
132
133void *MallocChecker::getTag() {
134  static int x;
135  return &x;
136}
137
138bool MallocChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) {
139  const GRState *state = C.getState();
140  const Expr *Callee = CE->getCallee();
141  SVal L = state->getSVal(Callee);
142
143  const FunctionDecl *FD = L.getAsFunctionDecl();
144  if (!FD)
145    return false;
146
147  ASTContext &Ctx = C.getASTContext();
148  if (!II_malloc)
149    II_malloc = &Ctx.Idents.get("malloc");
150  if (!II_free)
151    II_free = &Ctx.Idents.get("free");
152  if (!II_realloc)
153    II_realloc = &Ctx.Idents.get("realloc");
154  if (!II_calloc)
155    II_calloc = &Ctx.Idents.get("calloc");
156
157  if (FD->getIdentifier() == II_malloc) {
158    MallocMem(C, CE);
159    return true;
160  }
161
162  if (FD->getIdentifier() == II_free) {
163    FreeMem(C, CE);
164    return true;
165  }
166
167  if (FD->getIdentifier() == II_realloc) {
168    ReallocMem(C, CE);
169    return true;
170  }
171
172  if (FD->getIdentifier() == II_calloc) {
173    CallocMem(C, CE);
174    return true;
175  }
176
177  // Check all the attributes, if there are any.
178  // There can be multiple of these attributes.
179  bool rv = false;
180  if (FD->hasAttrs()) {
181    for (specific_attr_iterator<OwnershipAttr>
182                  i = FD->specific_attr_begin<OwnershipAttr>(),
183                  e = FD->specific_attr_end<OwnershipAttr>();
184         i != e; ++i) {
185      switch ((*i)->getOwnKind()) {
186      case OwnershipAttr::Returns: {
187        MallocMemReturnsAttr(C, CE, *i);
188        rv = true;
189        break;
190      }
191      case OwnershipAttr::Takes:
192      case OwnershipAttr::Holds: {
193        FreeMemAttr(C, CE, *i);
194        rv = true;
195        break;
196      }
197      default:
198        break;
199      }
200    }
201  }
202  return rv;
203}
204
205void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
206  const GRState *state = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(),
207                                      C.getState());
208  C.addTransition(state);
209}
210
211void MallocChecker::MallocMemReturnsAttr(CheckerContext &C, const CallExpr *CE,
212                                         const OwnershipAttr* Att) {
213  if (Att->getModule() != "malloc")
214    return;
215
216  OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
217  if (I != E) {
218    const GRState *state =
219        MallocMemAux(C, CE, CE->getArg(*I), UndefinedVal(), C.getState());
220    C.addTransition(state);
221    return;
222  }
223  const GRState *state = MallocMemAux(C, CE, UnknownVal(), UndefinedVal(),
224                                        C.getState());
225  C.addTransition(state);
226}
227
228const GRState *MallocChecker::MallocMemAux(CheckerContext &C,
229                                           const CallExpr *CE,
230                                           SVal Size, SVal Init,
231                                           const GRState *state) {
232  unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
233  SValBuilder &svalBuilder = C.getSValBuilder();
234
235  // Set the return value.
236  SVal retVal = svalBuilder.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
237  state = state->BindExpr(CE, retVal);
238
239  // Fill the region with the initialization value.
240  state = state->bindDefault(retVal, Init);
241
242  // Set the region's extent equal to the Size parameter.
243  const SymbolicRegion *R = cast<SymbolicRegion>(retVal.getAsRegion());
244  DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
245  DefinedOrUnknownSVal DefinedSize = cast<DefinedOrUnknownSVal>(Size);
246  DefinedOrUnknownSVal extentMatchesSize =
247    svalBuilder.evalEQ(state, Extent, DefinedSize);
248
249  state = state->assume(extentMatchesSize, true);
250  assert(state);
251
252  SymbolRef Sym = retVal.getAsLocSymbol();
253  assert(Sym);
254
255  // Set the symbol's state to Allocated.
256  return state->set<RegionState>(Sym, RefState::getAllocateUnchecked(CE));
257}
258
259void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
260  const GRState *state = FreeMemAux(C, CE, C.getState(), 0, false);
261
262  if (state)
263    C.addTransition(state);
264}
265
266void MallocChecker::FreeMemAttr(CheckerContext &C, const CallExpr *CE,
267                                const OwnershipAttr* Att) {
268  if (Att->getModule() != "malloc")
269    return;
270
271  for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
272       I != E; ++I) {
273    const GRState *state = FreeMemAux(C, CE, C.getState(), *I,
274                                      Att->getOwnKind() == OwnershipAttr::Holds);
275    if (state)
276      C.addTransition(state);
277  }
278}
279
280const GRState *MallocChecker::FreeMemAux(CheckerContext &C, const CallExpr *CE,
281                                         const GRState *state, unsigned Num,
282                                         bool Hold) {
283  const Expr *ArgExpr = CE->getArg(Num);
284  SVal ArgVal = state->getSVal(ArgExpr);
285
286  DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal);
287
288  // Check for null dereferences.
289  if (!isa<Loc>(location))
290    return state;
291
292  // FIXME: Technically using 'Assume' here can result in a path
293  //  bifurcation.  In such cases we need to return two states, not just one.
294  const GRState *notNullState, *nullState;
295  llvm::tie(notNullState, nullState) = state->assume(location);
296
297  // The explicit NULL case, no operation is performed.
298  if (nullState && !notNullState)
299    return nullState;
300
301  assert(notNullState);
302
303  // Unknown values could easily be okay
304  // Undefined values are handled elsewhere
305  if (ArgVal.isUnknownOrUndef())
306    return notNullState;
307
308  const MemRegion *R = ArgVal.getAsRegion();
309
310  // Nonlocs can't be freed, of course.
311  // Non-region locations (labels and fixed addresses) also shouldn't be freed.
312  if (!R) {
313    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
314    return NULL;
315  }
316
317  R = R->StripCasts();
318
319  // Blocks might show up as heap data, but should not be free()d
320  if (isa<BlockDataRegion>(R)) {
321    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
322    return NULL;
323  }
324
325  const MemSpaceRegion *MS = R->getMemorySpace();
326
327  // Parameters, locals, statics, and globals shouldn't be freed.
328  if (!(isa<UnknownSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS))) {
329    // FIXME: at the time this code was written, malloc() regions were
330    // represented by conjured symbols, which are all in UnknownSpaceRegion.
331    // This means that there isn't actually anything from HeapSpaceRegion
332    // that should be freed, even though we allow it here.
333    // Of course, free() can work on memory allocated outside the current
334    // function, so UnknownSpaceRegion is always a possibility.
335    // False negatives are better than false positives.
336
337    ReportBadFree(C, ArgVal, ArgExpr->getSourceRange());
338    return NULL;
339  }
340
341  const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R);
342  // Various cases could lead to non-symbol values here.
343  // For now, ignore them.
344  if (!SR)
345    return notNullState;
346
347  SymbolRef Sym = SR->getSymbol();
348  const RefState *RS = state->get<RegionState>(Sym);
349
350  // If the symbol has not been tracked, return. This is possible when free() is
351  // called on a pointer that does not get its pointee directly from malloc().
352  // Full support of this requires inter-procedural analysis.
353  if (!RS)
354    return notNullState;
355
356  // Check double free.
357  if (RS->isReleased()) {
358    if (ExplodedNode *N = C.generateSink()) {
359      if (!BT_DoubleFree)
360        BT_DoubleFree
361          = new BuiltinBug("Double free",
362                         "Try to free a memory block that has been released");
363      // FIXME: should find where it's freed last time.
364      BugReport *R = new BugReport(*BT_DoubleFree,
365                                   BT_DoubleFree->getDescription(), N);
366      C.EmitReport(R);
367    }
368    return NULL;
369  }
370
371  // Normal free.
372  if (Hold)
373    return notNullState->set<RegionState>(Sym, RefState::getRelinquished(CE));
374  return notNullState->set<RegionState>(Sym, RefState::getReleased(CE));
375}
376
377bool MallocChecker::SummarizeValue(llvm::raw_ostream& os, SVal V) {
378  if (nonloc::ConcreteInt *IntVal = dyn_cast<nonloc::ConcreteInt>(&V))
379    os << "an integer (" << IntVal->getValue() << ")";
380  else if (loc::ConcreteInt *ConstAddr = dyn_cast<loc::ConcreteInt>(&V))
381    os << "a constant address (" << ConstAddr->getValue() << ")";
382  else if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&V))
383    os << "the address of the label '" << Label->getLabel()->getName() << "'";
384  else
385    return false;
386
387  return true;
388}
389
390bool MallocChecker::SummarizeRegion(llvm::raw_ostream& os,
391                                    const MemRegion *MR) {
392  switch (MR->getKind()) {
393  case MemRegion::FunctionTextRegionKind: {
394    const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
395    if (FD)
396      os << "the address of the function '" << FD << "'";
397    else
398      os << "the address of a function";
399    return true;
400  }
401  case MemRegion::BlockTextRegionKind:
402    os << "block text";
403    return true;
404  case MemRegion::BlockDataRegionKind:
405    // FIXME: where the block came from?
406    os << "a block";
407    return true;
408  default: {
409    const MemSpaceRegion *MS = MR->getMemorySpace();
410
411    switch (MS->getKind()) {
412    case MemRegion::StackLocalsSpaceRegionKind: {
413      const VarRegion *VR = dyn_cast<VarRegion>(MR);
414      const VarDecl *VD;
415      if (VR)
416        VD = VR->getDecl();
417      else
418        VD = NULL;
419
420      if (VD)
421        os << "the address of the local variable '" << VD->getName() << "'";
422      else
423        os << "the address of a local stack variable";
424      return true;
425    }
426    case MemRegion::StackArgumentsSpaceRegionKind: {
427      const VarRegion *VR = dyn_cast<VarRegion>(MR);
428      const VarDecl *VD;
429      if (VR)
430        VD = VR->getDecl();
431      else
432        VD = NULL;
433
434      if (VD)
435        os << "the address of the parameter '" << VD->getName() << "'";
436      else
437        os << "the address of a parameter";
438      return true;
439    }
440    case MemRegion::NonStaticGlobalSpaceRegionKind:
441    case MemRegion::StaticGlobalSpaceRegionKind: {
442      const VarRegion *VR = dyn_cast<VarRegion>(MR);
443      const VarDecl *VD;
444      if (VR)
445        VD = VR->getDecl();
446      else
447        VD = NULL;
448
449      if (VD) {
450        if (VD->isStaticLocal())
451          os << "the address of the static variable '" << VD->getName() << "'";
452        else
453          os << "the address of the global variable '" << VD->getName() << "'";
454      } else
455        os << "the address of a global variable";
456      return true;
457    }
458    default:
459      return false;
460    }
461  }
462  }
463}
464
465void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
466                                  SourceRange range) {
467  if (ExplodedNode *N = C.generateSink()) {
468    if (!BT_BadFree)
469      BT_BadFree = new BuiltinBug("Bad free");
470
471    llvm::SmallString<100> buf;
472    llvm::raw_svector_ostream os(buf);
473
474    const MemRegion *MR = ArgVal.getAsRegion();
475    if (MR) {
476      while (const ElementRegion *ER = dyn_cast<ElementRegion>(MR))
477        MR = ER->getSuperRegion();
478
479      // Special case for alloca()
480      if (isa<AllocaRegion>(MR))
481        os << "Argument to free() was allocated by alloca(), not malloc()";
482      else {
483        os << "Argument to free() is ";
484        if (SummarizeRegion(os, MR))
485          os << ", which is not memory allocated by malloc()";
486        else
487          os << "not memory allocated by malloc()";
488      }
489    } else {
490      os << "Argument to free() is ";
491      if (SummarizeValue(os, ArgVal))
492        os << ", which is not memory allocated by malloc()";
493      else
494        os << "not memory allocated by malloc()";
495    }
496
497    EnhancedBugReport *R = new EnhancedBugReport(*BT_BadFree, os.str(), N);
498    R->addRange(range);
499    C.EmitReport(R);
500  }
501}
502
503void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) {
504  const GRState *state = C.getState();
505  const Expr *arg0Expr = CE->getArg(0);
506  DefinedOrUnknownSVal arg0Val
507    = cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr));
508
509  SValBuilder &svalBuilder = C.getSValBuilder();
510
511  DefinedOrUnknownSVal PtrEQ =
512    svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull());
513
514  // If the ptr is NULL, the call is equivalent to malloc(size).
515  if (const GRState *stateEqual = state->assume(PtrEQ, true)) {
516    // Hack: set the NULL symbolic region to released to suppress false warning.
517    // In the future we should add more states for allocated regions, e.g.,
518    // CheckedNull, CheckedNonNull.
519
520    SymbolRef Sym = arg0Val.getAsLocSymbol();
521    if (Sym)
522      stateEqual = stateEqual->set<RegionState>(Sym, RefState::getReleased(CE));
523
524    const GRState *stateMalloc = MallocMemAux(C, CE, CE->getArg(1),
525                                              UndefinedVal(), stateEqual);
526    C.addTransition(stateMalloc);
527  }
528
529  if (const GRState *stateNotEqual = state->assume(PtrEQ, false)) {
530    const Expr *Arg1 = CE->getArg(1);
531    DefinedOrUnknownSVal Arg1Val =
532      cast<DefinedOrUnknownSVal>(stateNotEqual->getSVal(Arg1));
533    DefinedOrUnknownSVal SizeZero =
534      svalBuilder.evalEQ(stateNotEqual, Arg1Val,
535                         svalBuilder.makeIntValWithPtrWidth(0, false));
536
537    if (const GRState *stateSizeZero = stateNotEqual->assume(SizeZero, true))
538      if (const GRState *stateFree = FreeMemAux(C, CE, stateSizeZero, 0, false))
539        C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true));
540
541    if (const GRState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false))
542      if (const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero,
543                                                0, false)) {
544        // FIXME: We should copy the content of the original buffer.
545        const GRState *stateRealloc = MallocMemAux(C, CE, CE->getArg(1),
546                                                   UnknownVal(), stateFree);
547        C.addTransition(stateRealloc);
548      }
549  }
550}
551
552void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
553  const GRState *state = C.getState();
554  SValBuilder &svalBuilder = C.getSValBuilder();
555
556  SVal count = state->getSVal(CE->getArg(0));
557  SVal elementSize = state->getSVal(CE->getArg(1));
558  SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize,
559                                        svalBuilder.getContext().getSizeType());
560  SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
561
562  C.addTransition(MallocMemAux(C, CE, TotalSize, zeroVal, state));
563}
564
565void MallocChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper)
566{
567  if (!SymReaper.hasDeadSymbols())
568    return;
569
570  const GRState *state = C.getState();
571  RegionStateTy RS = state->get<RegionState>();
572  RegionStateTy::Factory &F = state->get_context<RegionState>();
573
574  for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
575    if (SymReaper.isDead(I->first)) {
576      if (I->second.isAllocated()) {
577        if (ExplodedNode *N = C.generateNode()) {
578          if (!BT_Leak)
579            BT_Leak = new BuiltinBug("Memory leak",
580                     "Allocated memory never released. Potential memory leak.");
581          // FIXME: where it is allocated.
582          BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
583          C.EmitReport(R);
584        }
585      }
586
587      // Remove the dead symbol from the map.
588      RS = F.remove(RS, I->first);
589    }
590  }
591  C.generateNode(state->set<RegionState>(RS));
592}
593
594void MallocChecker::evalEndPath(EndOfFunctionNodeBuilder &B, void *tag,
595                                ExprEngine &Eng) {
596  const GRState *state = B.getState();
597  RegionStateTy M = state->get<RegionState>();
598
599  for (RegionStateTy::iterator I = M.begin(), E = M.end(); I != E; ++I) {
600    RefState RS = I->second;
601    if (RS.isAllocated()) {
602      ExplodedNode *N = B.generateNode(state, tag, B.getPredecessor());
603      if (N) {
604        if (!BT_Leak)
605          BT_Leak = new BuiltinBug("Memory leak",
606                     "Allocated memory never released. Potential memory leak.");
607        BugReport *R = new BugReport(*BT_Leak, BT_Leak->getDescription(), N);
608        Eng.getBugReporter().EmitReport(R);
609      }
610    }
611  }
612}
613
614void MallocChecker::PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S) {
615  const Expr *retExpr = S->getRetValue();
616  if (!retExpr)
617    return;
618
619  const GRState *state = C.getState();
620
621  SymbolRef Sym = state->getSVal(retExpr).getAsSymbol();
622  if (!Sym)
623    return;
624
625  const RefState *RS = state->get<RegionState>(Sym);
626  if (!RS)
627    return;
628
629  // FIXME: check other cases.
630  if (RS->isAllocated())
631    state = state->set<RegionState>(Sym, RefState::getEscaped(S));
632
633  C.addTransition(state);
634}
635
636const GRState *MallocChecker::evalAssume(const GRState *state, SVal Cond,
637                                         bool Assumption,
638                                         bool * /* respondsToCallback */) {
639  // If a symblic region is assumed to NULL, set its state to AllocateFailed.
640  // FIXME: should also check symbols assumed to non-null.
641
642  RegionStateTy RS = state->get<RegionState>();
643
644  for (RegionStateTy::iterator I = RS.begin(), E = RS.end(); I != E; ++I) {
645    if (state->getSymVal(I.getKey()))
646      state = state->set<RegionState>(I.getKey(),RefState::getAllocateFailed());
647  }
648
649  return state;
650}
651
652// Check if the location is a freed symbolic region.
653void MallocChecker::visitLocation(CheckerContext &C, const Stmt *S, SVal l,
654                                  bool isLoad) {
655  SymbolRef Sym = l.getLocSymbolInBase();
656  if (Sym) {
657    const RefState *RS = C.getState()->get<RegionState>(Sym);
658    if (RS && RS->isReleased()) {
659      if (ExplodedNode *N = C.generateNode()) {
660        if (!BT_UseFree)
661          BT_UseFree = new BuiltinBug("Use dynamically allocated memory after"
662                                      " it is freed.");
663
664        BugReport *R = new BugReport(*BT_UseFree, BT_UseFree->getDescription(),
665                                     N);
666        C.EmitReport(R);
667      }
668    }
669  }
670}
671
672void MallocChecker::PreVisitBind(CheckerContext &C,
673                                 const Stmt *StoreE,
674                                 SVal location,
675                                 SVal val) {
676  // The PreVisitBind implements the same algorithm as already used by the
677  // Objective C ownership checker: if the pointer escaped from this scope by
678  // assignment, let it go.  However, assigning to fields of a stack-storage
679  // structure does not transfer ownership.
680
681  const GRState *state = C.getState();
682  DefinedOrUnknownSVal l = cast<DefinedOrUnknownSVal>(location);
683
684  // Check for null dereferences.
685  if (!isa<Loc>(l))
686    return;
687
688  // Before checking if the state is null, check if 'val' has a RefState.
689  // Only then should we check for null and bifurcate the state.
690  SymbolRef Sym = val.getLocSymbolInBase();
691  if (Sym) {
692    if (const RefState *RS = state->get<RegionState>(Sym)) {
693      // If ptr is NULL, no operation is performed.
694      const GRState *notNullState, *nullState;
695      llvm::tie(notNullState, nullState) = state->assume(l);
696
697      // Generate a transition for 'nullState' to record the assumption
698      // that the state was null.
699      if (nullState)
700        C.addTransition(nullState);
701
702      if (!notNullState)
703        return;
704
705      if (RS->isAllocated()) {
706        // Something we presently own is being assigned somewhere.
707        const MemRegion *AR = location.getAsRegion();
708        if (!AR)
709          return;
710        AR = AR->StripCasts()->getBaseRegion();
711        do {
712          // If it is on the stack, we still own it.
713          if (AR->hasStackNonParametersStorage())
714            break;
715
716          // If the state can't represent this binding, we still own it.
717          if (notNullState == (notNullState->bindLoc(cast<Loc>(location),
718                                                     UnknownVal())))
719            break;
720
721          // We no longer own this pointer.
722          notNullState =
723            notNullState->set<RegionState>(Sym,
724                                           RefState::getRelinquished(StoreE));
725        }
726        while (false);
727      }
728      C.addTransition(notNullState);
729    }
730  }
731}
732