aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhongxing Xu <xuzhongxing@gmail.com>2009-11-13 07:48:11 +0000
committerZhongxing Xu <xuzhongxing@gmail.com>2009-11-13 07:48:11 +0000
commitfc7ac8f0b9ffd83b9e7329926e9e184586b49138 (patch)
treefdef3760b150e4f17b20ffea65f4be365e90da25
parent7b76096474b39505cf81573dcfece32f602408ee (diff)
Malloc checker basically works now.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@87094 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/MallocChecker.cpp26
-rw-r--r--test/Analysis/malloc.c13
2 files changed, 37 insertions, 2 deletions
diff --git a/lib/Analysis/MallocChecker.cpp b/lib/Analysis/MallocChecker.cpp
index f007aa65da..6655194d5e 100644
--- a/lib/Analysis/MallocChecker.cpp
+++ b/lib/Analysis/MallocChecker.cpp
@@ -30,11 +30,12 @@ class VISIBILITY_HIDDEN RegionState {};
class VISIBILITY_HIDDEN MallocChecker : public CheckerVisitor<MallocChecker> {
BuiltinBug *BT_DoubleFree;
+ BuiltinBug *BT_Leak;
IdentifierInfo *II_malloc;
IdentifierInfo *II_free;
public:
- MallocChecker() : BT_DoubleFree(0) {}
+ MallocChecker() : BT_DoubleFree(0), BT_Leak(0), II_malloc(0), II_free(0) {}
static void *getTag();
void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
void EvalDeadSymbols(CheckerContext &C,const Stmt *S,SymbolReaper &SymReaper);
@@ -81,7 +82,7 @@ void MallocChecker::PostVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
if (!II_malloc)
II_malloc = &Ctx.Idents.get("malloc");
if (!II_free)
- II_malloc = &Ctx.Idents.get("free");
+ II_free = &Ctx.Idents.get("free");
if (FD->getIdentifier() == II_malloc) {
MallocMem(C, CE);
@@ -135,4 +136,25 @@ void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
void MallocChecker::EvalDeadSymbols(CheckerContext &C, const Stmt *S,
SymbolReaper &SymReaper) {
+ for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(),
+ E = SymReaper.dead_end(); I != E; ++I) {
+ SymbolRef Sym = *I;
+ const GRState *state = C.getState();
+ const RefState *RS = state->get<RegionState>(Sym);
+ if (!RS)
+ return;
+
+ if (*RS == Allocated) {
+ ExplodedNode *N = C.GenerateNode(S, true);
+ if (N) {
+ if (!BT_Leak)
+ BT_Leak = new BuiltinBug("Memory leak",
+ "Allocated memory never released. Potential memory leak.");
+ // FIXME: where it is allocated.
+ BugReport *R = new BugReport(*BT_Leak,
+ BT_Leak->getDescription().c_str(), N);
+ C.EmitReport(R);
+ }
+ }
+ }
}
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
new file mode 100644
index 0000000000..270b3d1b69
--- /dev/null
+++ b/test/Analysis/malloc.c
@@ -0,0 +1,13 @@
+// RUN: clang-cc -analyze -checker-cfref -analyzer-experimental-checks -analyzer-store=region -verify %s
+#include <stdlib.h>
+
+void f1() {
+ int *p = malloc(10);
+ return; // expected-warning{{Allocated memory never released. Potential memory leak.}}
+}
+
+void f2() {
+ int *p = malloc(10);
+ free(p);
+ free(p); // expected-warning{{Try to free a memory block that has been released}}
+}