diff options
| author | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-06-18 02:47:46 +0000 |
|---|---|---|
| committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2010-06-18 02:47:46 +0000 |
| commit | e96a9132b89a808c4231e549a2748a52c731ba42 (patch) | |
| tree | ab6e24fbd43e1b3daf66a54e8545dae7e67621ee /clang/lib/Checker | |
| parent | 67d25f91c569761ff55e6875448a49e5b9addefd (diff) | |
| download | bcm5719-llvm-e96a9132b89a808c4231e549a2748a52c731ba42.tar.gz bcm5719-llvm-e96a9132b89a808c4231e549a2748a52c731ba42.zip | |
Add null stream check for more APIs.
llvm-svn: 106274
Diffstat (limited to 'clang/lib/Checker')
| -rw-r--r-- | clang/lib/Checker/StreamChecker.cpp | 86 |
1 files changed, 70 insertions, 16 deletions
diff --git a/clang/lib/Checker/StreamChecker.cpp b/clang/lib/Checker/StreamChecker.cpp index 01b7d83042e..44919f13391 100644 --- a/clang/lib/Checker/StreamChecker.cpp +++ b/clang/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; } |

