aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2014-04-01 03:40:53 +0000
committerJordan Rose <jordan_rose@apple.com>2014-04-01 03:40:53 +0000
commit3a176ed16d65e1ae08daa42e7145581817faebfa (patch)
treece376542358d1f0d58c9e045094bbe7ea9bf7f1b /clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
parent7fcaa14a82960c7e33a0c7aba881f32d18060b0c (diff)
downloadllvm-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.cpp39
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)