[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