aboutsummaryrefslogtreecommitdiff
path: root/lib/Checker/StreamChecker.cpp
diff options
context:
space:
mode:
authorZhongxing Xu <xuzhongxing@gmail.com>2010-06-18 02:47:46 +0000
committerZhongxing Xu <xuzhongxing@gmail.com>2010-06-18 02:47:46 +0000
commit23d90f90413ff1efd7e4410d28ae2cab99af1fdb (patch)
treefbf8d504833a72b4a4f290592e1d35a0360fb27c /lib/Checker/StreamChecker.cpp
parent568e598bf8e89b09a4ebc8c21430e1bd1ba6d11d (diff)
Add null stream check for more APIs.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106274 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Checker/StreamChecker.cpp')
-rw-r--r--lib/Checker/StreamChecker.cpp86
1 files changed, 70 insertions, 16 deletions
diff --git a/lib/Checker/StreamChecker.cpp b/lib/Checker/StreamChecker.cpp
index 01b7d83042..44919f1339 100644
--- a/lib/Checker/StreamChecker.cpp
+++ b/lib/Checker/StreamChecker.cpp
@@ -24,11 +24,13 @@ using namespace clang;
namespace {
class StreamChecker : public CheckerVisitor<StreamChecker> {
- IdentifierInfo *II_fopen, *II_fread;
+ IdentifierInfo *II_fopen, *II_fread, *II_fseek, *II_ftell, *II_rewind;
BuiltinBug *BT_nullfp;
public:
- StreamChecker() : II_fopen(0), II_fread(0), BT_nullfp(0) {}
+ StreamChecker()
+ : II_fopen(0), II_fread(0), II_fseek(0), II_ftell(0), II_rewind(0),
+ BT_nullfp(0) {}
static void *getTag() {
static int x;
@@ -40,9 +42,13 @@ public:
private:
void FOpen(CheckerContext &C, const CallExpr *CE);
void FRead(CheckerContext &C, const CallExpr *CE);
+ void FSeek(CheckerContext &C, const CallExpr *CE);
+ void FTell(CheckerContext &C, const CallExpr *CE);
+ void Rewind(CheckerContext &C, const CallExpr *CE);
+ bool CheckNullStream(SVal SV, const GRState *state, CheckerContext &C);
};
-}
+} // end anonymous namespace
void clang::RegisterStreamChecker(GRExprEngine &Eng) {
Eng.registerCheck(new StreamChecker());
@@ -63,6 +69,15 @@ bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
if (!II_fread)
II_fread = &Ctx.Idents.get("fread");
+ if (!II_fseek)
+ II_fseek = &Ctx.Idents.get("fseek");
+
+ if (!II_ftell)
+ II_ftell = &Ctx.Idents.get("ftell");
+
+ if (!II_rewind)
+ II_rewind = &Ctx.Idents.get("rewind");
+
if (FD->getIdentifier() == II_fopen) {
FOpen(C, CE);
return true;
@@ -73,6 +88,21 @@ bool StreamChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
return true;
}
+ if (FD->getIdentifier() == II_fseek) {
+ FSeek(C, CE);
+ return true;
+ }
+
+ if (FD->getIdentifier() == II_ftell) {
+ FTell(C, CE);
+ return true;
+ }
+
+ if (FD->getIdentifier() == II_rewind) {
+ Rewind(C, CE);
+ return true;
+ }
+
return false;
}
@@ -96,23 +126,47 @@ void StreamChecker::FOpen(CheckerContext &C, const CallExpr *CE) {
void StreamChecker::FRead(CheckerContext &C, const CallExpr *CE) {
const GRState *state = C.getState();
+ if (CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
+ return;
+}
+
+void StreamChecker::FSeek(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
+
+void StreamChecker::FTell(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
+
+void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) {
+ const GRState *state = C.getState();
+ if (CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+ return;
+}
- // Assume CallAndMessageChecker has been run.
- SVal StreamVal = state->getSVal(CE->getArg(3));
+bool StreamChecker::CheckNullStream(SVal SV, const GRState *state,
+ CheckerContext &C) {
+ const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV);
+ if (!DV)
+ return false;
- if (const DefinedSVal *DV = dyn_cast<DefinedSVal>(&StreamVal)) {
- ConstraintManager &CM = C.getConstraintManager();
- const GRState *stateNotNull, *stateNull;
- llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
+ ConstraintManager &CM = C.getConstraintManager();
+ const GRState *stateNotNull, *stateNull;
+ llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
- if (!stateNotNull && stateNull) {
- if (ExplodedNode *N = C.GenerateSink(stateNull)) {
- if (!BT_nullfp)
- BT_nullfp = new BuiltinBug("NULL stream pointer",
+ 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);
- }
+ BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N);
+ C.EmitReport(R);
}
+ return true;
}
+ return false;
}