NoQ created this revision.

It turns out that XNU rwlocks, locked by `lck_rw_lock_shared()` and 
`lck_rw_lock_exclusive()`, can be unlocked through either the "unspecific" 
`lck_rw_done()` or the "specific" `lck_rw_unlock_shared()` and 
`lck_rw_unlock_exclusive()` calls. Add the two "specific" unlock functions to 
the checker.


https://reviews.llvm.org/D37807

Files:
  lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
  test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h
  test/Analysis/pthreadlock.c


Index: test/Analysis/pthreadlock.c
===================================================================
--- test/Analysis/pthreadlock.c
+++ test/Analysis/pthreadlock.c
@@ -8,6 +8,7 @@
 pthread_mutex_t *pmtx;
 lck_mtx_t lck1, lck2;
 lck_grp_t grp1;
+lck_rw_t rw;
 
 #define NULL 0
 
@@ -213,6 +214,13 @@
   }
 }
 
+void ok29(void) {
+  lck_rw_lock_shared(&rw);
+  lck_rw_unlock_shared(&rw);
+  lck_rw_lock_exclusive(&rw); // no-warning
+  lck_rw_unlock_exclusive(&rw); // no-warning
+}
+
 void
 bad1(void)
 {
@@ -471,3 +479,10 @@
   if (ret != 0)
     pthread_mutex_lock(&mtx1);
 }
+
+void bad32(void) {
+  lck_rw_lock_shared(&rw);
+  lck_rw_unlock_exclusive(&rw); // FIXME: warn - should be shared?
+  lck_rw_lock_exclusive(&rw);
+  lck_rw_unlock_shared(&rw); // FIXME: warn - should be exclusive?
+}
Index: test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h
===================================================================
--- test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h
+++ test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h
@@ -15,6 +15,10 @@
        void    *foo;
 } lck_grp_t;
 
+typedef struct {
+  void *foo;
+} lck_rw_t;
+
 typedef pthread_mutex_t lck_mtx_t;
 
 extern int pthread_mutex_lock(pthread_mutex_t *);
@@ -28,3 +32,8 @@
 extern void lck_mtx_unlock(lck_mtx_t *);
 extern boolean_t lck_mtx_try_lock(lck_mtx_t *);
 extern void lck_mtx_destroy(lck_mtx_t *lck, lck_grp_t *grp);
+
+extern void lck_rw_lock_exclusive(lck_rw_t *lck);
+extern void lck_rw_unlock_exclusive(lck_rw_t *lck);
+extern void lck_rw_lock_shared(lck_rw_t *lck);
+extern void lck_rw_unlock_shared(lck_rw_t *lck);
Index: lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -141,6 +141,8 @@
   else if (FName == "pthread_mutex_unlock" ||
            FName == "pthread_rwlock_unlock" ||
            FName == "lck_mtx_unlock" ||
+           FName == "lck_rw_unlock_exclusive" ||
+           FName == "lck_rw_unlock_shared" ||
            FName == "lck_rw_done")
     ReleaseLock(C, CE, state->getSVal(CE->getArg(0), LCtx));
   else if (FName == "pthread_mutex_destroy")


Index: test/Analysis/pthreadlock.c
===================================================================
--- test/Analysis/pthreadlock.c
+++ test/Analysis/pthreadlock.c
@@ -8,6 +8,7 @@
 pthread_mutex_t *pmtx;
 lck_mtx_t lck1, lck2;
 lck_grp_t grp1;
+lck_rw_t rw;
 
 #define NULL 0
 
@@ -213,6 +214,13 @@
   }
 }
 
+void ok29(void) {
+  lck_rw_lock_shared(&rw);
+  lck_rw_unlock_shared(&rw);
+  lck_rw_lock_exclusive(&rw); // no-warning
+  lck_rw_unlock_exclusive(&rw); // no-warning
+}
+
 void
 bad1(void)
 {
@@ -471,3 +479,10 @@
   if (ret != 0)
     pthread_mutex_lock(&mtx1);
 }
+
+void bad32(void) {
+  lck_rw_lock_shared(&rw);
+  lck_rw_unlock_exclusive(&rw); // FIXME: warn - should be shared?
+  lck_rw_lock_exclusive(&rw);
+  lck_rw_unlock_shared(&rw); // FIXME: warn - should be exclusive?
+}
Index: test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h
===================================================================
--- test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h
+++ test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h
@@ -15,6 +15,10 @@
 	void	*foo;
 } lck_grp_t;
 
+typedef struct {
+  void *foo;
+} lck_rw_t;
+
 typedef pthread_mutex_t lck_mtx_t;
 
 extern int pthread_mutex_lock(pthread_mutex_t *);
@@ -28,3 +32,8 @@
 extern void lck_mtx_unlock(lck_mtx_t *);
 extern boolean_t lck_mtx_try_lock(lck_mtx_t *);
 extern void lck_mtx_destroy(lck_mtx_t *lck, lck_grp_t *grp);
+
+extern void lck_rw_lock_exclusive(lck_rw_t *lck);
+extern void lck_rw_unlock_exclusive(lck_rw_t *lck);
+extern void lck_rw_lock_shared(lck_rw_t *lck);
+extern void lck_rw_unlock_shared(lck_rw_t *lck);
Index: lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -141,6 +141,8 @@
   else if (FName == "pthread_mutex_unlock" ||
            FName == "pthread_rwlock_unlock" ||
            FName == "lck_mtx_unlock" ||
+           FName == "lck_rw_unlock_exclusive" ||
+           FName == "lck_rw_unlock_shared" ||
            FName == "lck_rw_done")
     ReleaseLock(C, CE, state->getSVal(CE->getArg(0), LCtx));
   else if (FName == "pthread_mutex_destroy")
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to