r205276 - [analyzer] Lock checker: Allow pthread_mutex_init to reinitialize a destroyed lock.
Jordan Rose
jordan_rose at apple.com
Mon Mar 31 20:40:53 PDT 2014
Author: jrose
Date: Mon Mar 31 22:40:53 2014
New Revision: 205276
URL: http://llvm.org/viewvc/llvm-project?rev=205276&view=rev
Log:
[analyzer] Lock checker: Allow pthread_mutex_init to reinitialize a destroyed lock.
Patch by Daniel Fahlgren!
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
cfe/trunk/test/Analysis/pthreadlock.c
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp?rev=205276&r1=205275&r2=205276&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp Mon Mar 31 22:40:53 2014
@@ -53,6 +53,7 @@ class PthreadLockChecker : public Checke
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(c
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,
@@ -279,6 +283,41 @@ void PthreadLockChecker::DestroyLock(Che
Report->addRange(CE->getArg(0)->getSourceRange());
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 {
Modified: cfe/trunk/test/Analysis/pthreadlock.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/pthreadlock.c?rev=205276&r1=205275&r2=205276&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/pthreadlock.c (original)
+++ cfe/trunk/test/Analysis/pthreadlock.c Mon Mar 31 22:40:53 2014
@@ -8,6 +8,10 @@ typedef struct {
typedef struct {
void *foo;
+} pthread_mutexattr_t;
+
+typedef struct {
+ void *foo;
} lck_grp_t;
typedef pthread_mutex_t lck_mtx_t;
@@ -16,6 +20,7 @@ extern int pthread_mutex_lock(pthread_mu
extern int pthread_mutex_unlock(pthread_mutex_t *);
extern int pthread_mutex_trylock(pthread_mutex_t *);
extern int pthread_mutex_destroy(pthread_mutex_t *);
+extern int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
extern int lck_mtx_lock(lck_mtx_t *);
extern int lck_mtx_unlock(lck_mtx_t *);
extern int lck_mtx_try_lock(lck_mtx_t *);
@@ -25,6 +30,8 @@ pthread_mutex_t mtx1, mtx2;
lck_mtx_t lck1, lck2;
lck_grp_t grp1;
+#define NULL 0
+
void
ok1(void)
{
@@ -138,6 +145,45 @@ ok15(void)
}
void
+ok16(void)
+{
+ pthread_mutex_init(&mtx1, NULL); // no-warning
+}
+
+void
+ok17(void)
+{
+ pthread_mutex_init(&mtx1, NULL); // no-warning
+ pthread_mutex_init(&mtx2, NULL); // no-warning
+}
+
+void
+ok18(void)
+{
+ pthread_mutex_destroy(&mtx1); // no-warning
+ pthread_mutex_init(&mtx1, NULL); // no-warning
+}
+
+void
+ok19(void)
+{
+ pthread_mutex_destroy(&mtx1); // no-warning
+ pthread_mutex_init(&mtx1, NULL); // no-warning
+ pthread_mutex_destroy(&mtx2); // no-warning
+ pthread_mutex_init(&mtx2, NULL); // no-warning
+}
+
+void
+ok20(void)
+{
+ pthread_mutex_unlock(&mtx1); // no-warning
+ pthread_mutex_destroy(&mtx1); // no-warning
+ pthread_mutex_init(&mtx1, NULL); // no-warning
+ pthread_mutex_destroy(&mtx1); // no-warning
+ pthread_mutex_init(&mtx1, NULL); // no-warning
+}
+
+void
bad1(void)
{
pthread_mutex_lock(&mtx1); // no-warning
@@ -331,3 +377,24 @@ bad23(void)
lck_mtx_lock(&mtx1); // no-warning
lck_mtx_destroy(&mtx1, &grp1); // expected-warning{{This lock is still locked}}
}
+
+void
+bad24(void)
+{
+ pthread_mutex_init(&mtx1, NULL); // no-warning
+ pthread_mutex_init(&mtx1, NULL); // expected-warning{{This lock has already been initialized}}
+}
+
+void
+bad25(void)
+{
+ pthread_mutex_lock(&mtx1); // no-warning
+ pthread_mutex_init(&mtx1, NULL); // expected-warning{{This lock is still being held}}
+}
+
+void
+bad26(void)
+{
+ pthread_mutex_unlock(&mtx1); // no-warning
+ pthread_mutex_init(&mtx1, NULL); // expected-warning{{This lock has already been initialized}}
+}
More information about the cfe-commits
mailing list