Make pthread stack size match real range.

Bug: 18908062
Change-Id: I7037ac8273ebe54dd19b1561c7a376819049124c
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 7e74dac..e4abee9 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -158,6 +158,7 @@
   //   thread stack (including guard page)
   stack_top -= sizeof(pthread_internal_t);
   pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top);
+  attr->stack_size = stack_top - reinterpret_cast<uint8_t*>(attr->stack_base);
 
   // No need to check stack_top alignment. The size of pthread_internal_t is 16-bytes aligned,
   // and user allocated stack is guaranteed by pthread_attr_setstack.
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 1418c76..2398f23 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -32,7 +32,6 @@
 #include <time.h>
 #include <unistd.h>
 
-
 TEST(pthread, pthread_key_create) {
   pthread_key_t key;
   ASSERT_EQ(0, pthread_key_create(&key, NULL));
@@ -633,18 +632,18 @@
   ASSERT_EQ(default_stack_size, stack_size);
   ASSERT_GE(GetActualStackSize(attributes), default_stack_size);
 
-  // Large enough and a multiple of the page size.
+  // Large enough and a multiple of the page size; may be rounded up by pthread_create.
   ASSERT_EQ(0, pthread_attr_setstacksize(&attributes, 32*1024));
   ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size));
   ASSERT_EQ(32*1024U, stack_size);
-  ASSERT_EQ(GetActualStackSize(attributes), 32*1024U);
+  ASSERT_GE(GetActualStackSize(attributes), 32*1024U);
 
-  // Large enough but not a multiple of the page size; will be rounded up by pthread_create.
+  // Large enough but not aligned; will be rounded up by pthread_create.
   ASSERT_EQ(0, pthread_attr_setstacksize(&attributes, 32*1024 + 1));
   ASSERT_EQ(0, pthread_attr_getstacksize(&attributes, &stack_size));
   ASSERT_EQ(32*1024U + 1, stack_size);
 #if defined(__BIONIC__)
-  ASSERT_EQ(GetActualStackSize(attributes), 32*1024U + 1);
+  ASSERT_GT(GetActualStackSize(attributes), 32*1024U + 1);
 #else // __BIONIC__
   // glibc rounds down, in violation of POSIX. They document this in their BUGS section.
   ASSERT_EQ(GetActualStackSize(attributes), 32*1024U);
@@ -939,6 +938,29 @@
   ASSERT_EQ(6666U, stack_size);
 }
 
+static void pthread_attr_getstack_18908062_helper(void*) {
+  char local_variable;
+  pthread_attr_t attributes;
+  pthread_getattr_np(pthread_self(), &attributes);
+  void* stack_base;
+  size_t stack_size;
+  pthread_attr_getstack(&attributes, &stack_base, &stack_size);
+
+  // Test whether &local_variable is in [stack_base, stack_base + stack_size).
+  ASSERT_LE(reinterpret_cast<char*>(stack_base), &local_variable);
+  ASSERT_LT(&local_variable, reinterpret_cast<char*>(stack_base) + stack_size);
+}
+
+// Check whether something on stack is in the range of
+// [stack_base, stack_base + stack_size). see b/18908062.
+TEST(pthread, pthread_attr_getstack_18908062) {
+  pthread_t t;
+  ASSERT_EQ(0, pthread_create(&t, NULL,
+            reinterpret_cast<void* (*)(void*)>(pthread_attr_getstack_18908062_helper),
+            NULL));
+  pthread_join(t, NULL);
+}
+
 #if defined(__BIONIC__)
 static void* pthread_gettid_np_helper(void* arg) {
   *reinterpret_cast<pid_t*>(arg) = gettid();