[cfe-commits] r86978 - /cfe/trunk/lib/Analysis/MallocChecker.cpp

Zhongxing Xu xuzhongxing at gmail.com
Thu Nov 12 00:38:57 PST 2009


Author: zhongxingxu
Date: Thu Nov 12 02:38:56 2009
New Revision: 86978

URL: http://llvm.org/viewvc/llvm-project?rev=86978&view=rev
Log:
Add boilerplate logic for a malloc/free checker.

Added:
    cfe/trunk/lib/Analysis/MallocChecker.cpp

Added: cfe/trunk/lib/Analysis/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/MallocChecker.cpp?rev=86978&view=auto

==============================================================================
--- cfe/trunk/lib/Analysis/MallocChecker.cpp (added)
+++ cfe/trunk/lib/Analysis/MallocChecker.cpp Thu Nov 12 02:38:56 2009
@@ -0,0 +1,126 @@
+//=== MallocChecker.cpp - A malloc/free checker -------------------*- C++ -*--//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines malloc/free checker, which checks for potential memory
+// leaks, double free, and use-after-free problems.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
+#include "clang/Analysis/PathSensitive/GRState.h"
+#include "clang/Analysis/PathSensitive/GRStateTrait.h"
+#include "clang/Analysis/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+using namespace clang;
+
+namespace {
+
+enum RefState {
+  Allocated, Released, Escaped
+};
+
+class VISIBILITY_HIDDEN RegionState {};
+
+class VISIBILITY_HIDDEN MallocChecker : CheckerVisitor<MallocChecker> {
+  BuiltinBug *BT_DoubleFree;
+  IdentifierInfo *II_malloc;
+  IdentifierInfo *II_free;
+
+public:
+  static void *getTag();
+  void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+  void MallocMem(CheckerContext &C, const CallExpr *CE);
+  void FreeMem(CheckerContext &C, const CallExpr *CE);
+};
+}
+
+namespace llvm {
+  template<> struct FoldingSetTrait<RefState> {
+    static void Profile(const RefState &X, FoldingSetNodeID &ID) { 
+      ID.AddInteger(X);
+    }
+    static void Profile(RefState &X, FoldingSetNodeID &ID) { 
+      ID.AddInteger(X);
+    }
+  };
+}
+
+namespace clang {
+  template<>
+  struct GRStateTrait<RegionState> 
+    : public GRStatePartialTrait<llvm::ImmutableMap<SymbolRef, RefState> > {
+    static void *GDMIndex() { return MallocChecker::getTag(); }
+  };
+}
+
+void *MallocChecker::getTag() {
+  static int x;
+  return &x;
+}
+
+void MallocChecker::PostVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+  const FunctionDecl *FD = CE->getDirectCallee();
+  if (!FD)
+    return;
+
+  ASTContext &Ctx = C.getASTContext();
+  if (!II_malloc)
+    II_malloc = &Ctx.Idents.get("malloc");
+  if (!II_free)
+    II_malloc = &Ctx.Idents.get("free");
+
+  if (FD->getIdentifier() == II_malloc) {
+    MallocMem(C, CE);
+    return;
+  }
+
+  if (FD->getIdentifier() == II_free) {
+    FreeMem(C, CE);
+    return;
+  }
+}
+
+void MallocChecker::MallocMem(CheckerContext &C, const CallExpr *CE) {
+  const GRState *state = C.getState();
+  SVal CallVal = state->getSVal(CE);
+  SymbolRef Sym = CallVal.getAsLocSymbol();
+  assert(Sym);
+  // Set the symbol's state to Allocated.
+  const GRState *AllocState = state->set<RegionState>(Sym, Allocated);
+  C.addTransition(C.GenerateNode(CE, AllocState));
+}
+
+void MallocChecker::FreeMem(CheckerContext &C, const CallExpr *CE) {
+  const GRState *state = C.getState();
+  SVal ArgVal = state->getSVal(CE->getArg(0));
+  SymbolRef Sym = ArgVal.getAsLocSymbol();
+  assert(Sym);
+
+  const RefState *RS = state->get<RegionState>(Sym);
+  assert(RS);
+
+  // Check double free.
+  if (*RS == Released) {
+    ExplodedNode *N = C.GenerateNode(CE, true);
+    if (N) {
+      if (!BT_DoubleFree)
+        BT_DoubleFree = new BuiltinBug("Double free",
+                         "Try to free a memory block that has been released");
+      // FIXME: should find where it's freed last time.
+      BugReport *R = new BugReport(*BT_DoubleFree, 
+                                   BT_DoubleFree->getDescription().c_str(), N);
+      C.EmitReport(R);
+    }
+    return;
+  }
+
+  // Normal free.
+  const GRState *FreedState = state->set<RegionState>(Sym, Released);
+  C.addTransition(C.GenerateNode(CE, FreedState));
+}





More information about the cfe-commits mailing list