MallocChecker.cpp 25 KB

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