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