OSDN Git Service

Allow NULL in pthread_mutex_lock/unlock.
authorChristopher Ferris <cferris@google.com>
Wed, 10 Jun 2015 01:46:15 +0000 (18:46 -0700)
committerChristopher Ferris <cferris@google.com>
Wed, 10 Jun 2015 01:46:15 +0000 (18:46 -0700)
The pthread_mutex_lock and pthread_mutex_unlock were allowed to
fail silently on L 32 bit devices when passed a NULL. We changed
this to a crash on 32 bit devices, but there are still games that make
these calls and are not likely to be updated. Therefore, once again
allow NULL to be passed in on 32 bit devices.

Bug: 19995172
Change-Id: If7e8860075ecd63c0064d80f64e226fad7bd3c26

libc/bionic/pthread_mutex.cpp
libc/include/pthread.h
tests/pthread_test.cpp

index 4fec753..851fc3d 100644 (file)
@@ -501,6 +501,12 @@ static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex,
 }
 
 int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {
+#if !defined(__LP64__)
+    if (mutex_interface == NULL) {
+        return EINVAL;
+    }
+#endif
+
     pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
 
     uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
@@ -516,6 +522,12 @@ int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {
 }
 
 int pthread_mutex_unlock(pthread_mutex_t* mutex_interface) {
+#if !defined(__LP64__)
+    if (mutex_interface == NULL) {
+        return EINVAL;
+    }
+#endif
+
     pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
 
     uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
index 26d68e4..260ae5b 100644 (file)
@@ -176,10 +176,18 @@ int pthread_mutexattr_settype(pthread_mutexattr_t*, int) __nonnull((1));
 
 int pthread_mutex_destroy(pthread_mutex_t*) __nonnull((1));
 int pthread_mutex_init(pthread_mutex_t*, const pthread_mutexattr_t*) __nonnull((1));
+#if !defined(__LP64__)
+int pthread_mutex_lock(pthread_mutex_t*) /* __nonnull((1)) */;
+#else
 int pthread_mutex_lock(pthread_mutex_t*) __nonnull((1));
+#endif
 int pthread_mutex_timedlock(pthread_mutex_t*, const struct timespec*) __nonnull((1, 2));
 int pthread_mutex_trylock(pthread_mutex_t*) __nonnull((1));
+#if !defined(__LP4__)
+int pthread_mutex_unlock(pthread_mutex_t*) /* __nonnull((1)) */;
+#else
 int pthread_mutex_unlock(pthread_mutex_t*) __nonnull((1));
+#endif
 
 int pthread_once(pthread_once_t*, void (*)(void)) __nonnull((1, 2));
 
index 201b8a9..8ae28d8 100644 (file)
@@ -1537,3 +1537,37 @@ TEST(pthread, pthread_types_allow_four_bytes_alignment) {
   GTEST_LOG_(INFO) << "This test tests bionic implementation details.";
 #endif
 }
+
+TEST(pthread, pthread_mutex_lock_null_32) {
+#if defined(__BIONIC__) && !defined(__LP64__)
+  ASSERT_EQ(EINVAL, pthread_mutex_lock(NULL));
+#else
+  GTEST_LOG_(INFO) << "This test tests bionic implementation details on 32 bit devices.";
+#endif
+}
+
+TEST(pthread, pthread_mutex_unlock_null_32) {
+#if defined(__BIONIC__) && !defined(__LP64__)
+  ASSERT_EQ(EINVAL, pthread_mutex_unlock(NULL));
+#else
+  GTEST_LOG_(INFO) << "This test tests bionic implementation details on 32 bit devices.";
+#endif
+}
+
+TEST_F(pthread_DeathTest, pthread_mutex_lock_null_64) {
+#if defined(__BIONIC__) && defined(__LP64__)
+  pthread_mutex_t* null_value = nullptr;
+  ASSERT_EXIT(pthread_mutex_lock(null_value), testing::KilledBySignal(SIGSEGV), "");
+#else
+  GTEST_LOG_(INFO) << "This test tests bionic implementation details on 64 bit devices.";
+#endif
+}
+
+TEST_F(pthread_DeathTest, pthread_mutex_unlock_null_64) {
+#if defined(__BIONIC__) && defined(__LP64__)
+  pthread_mutex_t* null_value = nullptr;
+  ASSERT_EXIT(pthread_mutex_unlock(null_value), testing::KilledBySignal(SIGSEGV), "");
+#else
+  GTEST_LOG_(INFO) << "This test tests bionic implementation details on 64 bit devices.";
+#endif
+}