diff options
author | Jordan Rose <jordan_rose@apple.com> | 2014-04-01 03:40:53 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2014-04-01 03:40:53 +0000 |
commit | 3a176ed16d65e1ae08daa42e7145581817faebfa (patch) | |
tree | ce376542358d1f0d58c9e045094bbe7ea9bf7f1b /clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp | |
parent | 7fcaa14a82960c7e33a0c7aba881f32d18060b0c (diff) | |
download | llvm-3a176ed16d65e1ae08daa42e7145581817faebfa.zip llvm-3a176ed16d65e1ae08daa42e7145581817faebfa.tar.gz llvm-3a176ed16d65e1ae08daa42e7145581817faebfa.tar.bz2 |
[analyzer] Lock checker: Allow pthread_mutex_init to reinitialize a destroyed lock.
Patch by Daniel Fahlgren!
llvm-svn: 205276
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index 76ae027..1ede3a2 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -53,6 +53,7 @@ class PthreadLockChecker : public Checker< check::PostStmt<CallExpr> > { mutable std::unique_ptr<BugType> BT_doublelock; mutable std::unique_ptr<BugType> BT_doubleunlock; mutable std::unique_ptr<BugType> BT_destroylock; + mutable std::unique_ptr<BugType> BT_initlock; mutable std::unique_ptr<BugType> BT_lor; enum LockingSemantics { NotApplicable = 0, @@ -67,6 +68,7 @@ public: void ReleaseLock(CheckerContext &C, const CallExpr *CE, SVal lock) const; void DestroyLock(CheckerContext &C, const CallExpr *CE, SVal Lock) const; + void InitLock(CheckerContext &C, const CallExpr *CE, SVal Lock) const; void reportUseDestroyedBug(CheckerContext &C, const CallExpr *CE) const; }; } // end anonymous namespace @@ -115,6 +117,8 @@ void PthreadLockChecker::checkPostStmt(const CallExpr *CE, else if (FName == "pthread_mutex_destroy" || FName == "lck_mtx_destroy") DestroyLock(C, CE, state->getSVal(CE->getArg(0), LCtx)); + else if (FName == "pthread_mutex_init") + InitLock(C, CE, state->getSVal(CE->getArg(0), LCtx)); } void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE, @@ -280,6 +284,41 @@ void PthreadLockChecker::DestroyLock(CheckerContext &C, const CallExpr *CE, C.emitReport(Report); } +void PthreadLockChecker::InitLock(CheckerContext &C, const CallExpr *CE, + SVal Lock) const { + + const MemRegion *LockR = Lock.getAsRegion(); + if (!LockR) + return; + + ProgramStateRef State = C.getState(); + + const struct LockState *LState = State->get<LockMap>(LockR); + if (!LState || LState->isDestroyed()) { + State = State->set<LockMap>(LockR, LockState::getUnlocked()); + C.addTransition(State); + return; + } + + StringRef Message; + + if (LState->isLocked()) { + Message = "This lock is still being held"; + } else { + Message = "This lock has already been initialized"; + } + + if (!BT_initlock) + BT_initlock.reset(new BugType(this, "Init invalid lock", + "Lock checker")); + ExplodedNode *N = C.generateSink(); + if (!N) + return; + BugReport *Report = new BugReport(*BT_initlock, Message, N); + Report->addRange(CE->getArg(0)->getSourceRange()); + C.emitReport(Report); +} + void PthreadLockChecker::reportUseDestroyedBug(CheckerContext &C, const CallExpr *CE) const { if (!BT_destroylock) |