[cfe-commits] r106082 - in /cfe/trunk: include/clang/Checker/PathSensitive/Checker.h lib/Checker/CMakeLists.txt lib/Checker/GRExprEngineExperimentalChecks.cpp lib/Checker/GRExprEngineExperimentalChecks.h lib/Checker/StreamChecker.cpp test/Analysis/stream.c

Zhongxing Xu xuzhongxing at gmail.com
Tue Jun 15 22:38:06 PDT 2010


Author: zhongxingxu
Date: Wed Jun 16 00:38:05 2010
New Revision: 106082

URL: http://llvm.org/viewvc/llvm-project?rev=106082&view=rev
Log:
Add StreamChecker. This checker models and checks stream manipulation functions.
This is the start.

Added:
    cfe/trunk/lib/Checker/StreamChecker.cpp
    cfe/trunk/test/Analysis/stream.c
Modified:
    cfe/trunk/include/clang/Checker/PathSensitive/Checker.h
    cfe/trunk/lib/Checker/CMakeLists.txt
    cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp
    cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.h

Modified: cfe/trunk/include/clang/Checker/PathSensitive/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Checker/PathSensitive/Checker.h?rev=106082&r1=106081&r2=106082&view=diff
==============================================================================
--- cfe/trunk/include/clang/Checker/PathSensitive/Checker.h (original)
+++ cfe/trunk/include/clang/Checker/PathSensitive/Checker.h Wed Jun 16 00:38:05 2010
@@ -144,6 +144,7 @@
     // If the 'state' is not new, we need to check if the cached state 'ST'
     // is new.
     if (state != getState() || (ST && ST != B.GetState(Pred)))
+      // state is new or equals to ST.
       GenerateNode(state, true);
     else
       Dst.Add(Pred);

Modified: cfe/trunk/lib/Checker/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/CMakeLists.txt?rev=106082&r1=106081&r2=106082&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/CMakeLists.txt (original)
+++ cfe/trunk/lib/Checker/CMakeLists.txt Wed Jun 16 00:38:05 2010
@@ -62,6 +62,7 @@
   SimpleSValuator.cpp
   StackAddrLeakChecker.cpp
   Store.cpp
+  StreamChecker.cpp
   SVals.cpp
   SValuator.cpp
   SymbolManager.cpp

Modified: cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp?rev=106082&r1=106081&r2=106082&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp (original)
+++ cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.cpp Wed Jun 16 00:38:05 2010
@@ -23,6 +23,7 @@
   // within GRExprEngine.
   RegisterPthreadLockChecker(Eng);  
   RegisterMallocChecker(Eng);
+  RegisterStreamChecker(Eng);
 }
 
 void clang::RegisterExperimentalInternalChecks(GRExprEngine &Eng) {

Modified: cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.h?rev=106082&r1=106081&r2=106082&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.h (original)
+++ cfe/trunk/lib/Checker/GRExprEngineExperimentalChecks.h Wed Jun 16 00:38:05 2010
@@ -21,6 +21,7 @@
 
 void RegisterPthreadLockChecker(GRExprEngine &Eng);
 void RegisterMallocChecker(GRExprEngine &Eng);
+void RegisterStreamChecker(GRExprEngine &Eng);
 
 } // end clang namespace
 #endif

Added: cfe/trunk/lib/Checker/StreamChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/StreamChecker.cpp?rev=106082&view=auto
==============================================================================
--- cfe/trunk/lib/Checker/StreamChecker.cpp (added)
+++ cfe/trunk/lib/Checker/StreamChecker.cpp Wed Jun 16 00:38:05 2010
@@ -0,0 +1,116 @@
+//===-- StreamChecker.cpp -----------------------------------------*- 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 checkers that model and check stream handling functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GRExprEngineExperimentalChecks.h"
+#include "clang/Checker/BugReporter/BugType.h"
+#include "clang/Checker/PathSensitive/CheckerVisitor.h"
+#include "clang/Checker/PathSensitive/GRState.h"
+#include "clang/Checker/PathSensitive/GRStateTrait.h"
+#include "clang/Checker/PathSensitive/SymbolManager.h"
+#include "llvm/ADT/ImmutableMap.h"
+
+using namespace clang;
+
+namespace {
+
+class StreamChecker : public CheckerVisitor<StreamChecker> {
+  IdentifierInfo *II_fopen, *II_fread;
+  BuiltinBug *BT_nullfp;
+
+public:
+  StreamChecker() : II_fopen(0), II_fread(0), BT_nullfp(0) {}
+
+  static void *getTag() {
+    static int x;
+    return &x;
+  }
+
+  virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
+
+private:
+  void FOpen(CheckerContext &C, const CallExpr *CE);
+  void FRead(CheckerContext &C, const CallExpr *CE);
+};
+
+}
+
+void clang::RegisterStreamChecker(GRExprEngine &Eng) {
+  Eng.registerCheck(new StreamChecker());
+}
+
+bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
+  const GRState *state = C.getState();
+  const Expr *Callee = CE->getCallee();
+  SVal L = state->getSVal(Callee);
+  const FunctionDecl *FD = L.getAsFunctionDecl();
+  if (!FD)
+    return false;
+
+  ASTContext &Ctx = C.getASTContext();
+  if (!II_fopen)
+    II_fopen = &Ctx.Idents.get("fopen");
+
+  if (!II_fread)
+    II_fread = &Ctx.Idents.get("fread");
+
+  if (FD->getIdentifier() == II_fopen) {
+    FOpen(C, CE);
+    return true;
+  }
+
+  if (FD->getIdentifier() == II_fread) {
+    FRead(C, CE);
+    return true;
+  }
+
+  return false;
+}
+
+void StreamChecker::FOpen(CheckerContext &C, const CallExpr *CE) {
+  const GRState *state = C.getState();
+  unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
+  ValueManager &ValMgr = C.getValueManager();
+  SVal RetVal = ValMgr.getConjuredSymbolVal(0, CE, Count);
+  state = state->BindExpr(CE, RetVal);
+
+  ConstraintManager &CM = C.getConstraintManager();
+  // Bifurcate the state into two: one with a valid FILE* pointer, the other
+  // with a NULL.
+  const GRState *stateNotNull, *stateNull;
+  llvm::tie(stateNotNull, stateNull) 
+    = CM.AssumeDual(state, cast<DefinedSVal>(RetVal));
+
+  C.addTransition(stateNotNull);
+  C.addTransition(stateNull);
+}
+
+void StreamChecker::FRead(CheckerContext &C, const CallExpr *CE) {
+  const GRState *state = C.getState();
+
+  // Assume CallAndMessageChecker has been run.
+  const DefinedSVal &StreamVal=cast<DefinedSVal>(state->getSVal(CE->getArg(3)));
+
+  ConstraintManager &CM = C.getConstraintManager();
+  const GRState *stateNotNull, *stateNull;
+  llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, StreamVal);
+
+  if (!stateNotNull && stateNull) {
+    if (ExplodedNode *N = C.GenerateSink(stateNull)) {
+      if (!BT_nullfp)
+        BT_nullfp = new BuiltinBug("NULL stream pointer",
+                                   "Stream pointer might be NULL.");
+      BugReport *R = new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N);
+      C.EmitReport(R);
+    }
+  }
+}

Added: cfe/trunk/test/Analysis/stream.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/stream.c?rev=106082&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/stream.c (added)
+++ cfe/trunk/test/Analysis/stream.c Wed Jun 16 00:38:05 2010
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-experimental-checks -analyzer-store region -verify %s
+
+typedef __typeof__(sizeof(int)) size_t;
+typedef struct _IO_FILE FILE;
+FILE *fopen(const char *path, const char *mode);
+size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
+
+void f1(void) {
+  FILE *p = fopen("foo", "r");
+  char buf[1024];
+  fread(buf, 1, 1, p); // expected-warning {{Stream pointer might be NULL.}}
+}





More information about the cfe-commits mailing list