Merge "Ignore all __weak_alias in OpenBSD libC."
diff --git a/libc/bionic/libc_logging.cpp b/libc/bionic/libc_logging.cpp
index 5655526..49a3762 100644
--- a/libc/bionic/libc_logging.cpp
+++ b/libc/bionic/libc_logging.cpp
@@ -75,10 +75,12 @@
       len = strlen(data);
     }
 
+    total += len;
+
     while (len > 0) {
       int avail = end_ - pos_;
       if (avail == 0) {
-        break;
+        return;
       }
       if (avail > len) {
         avail = len;
@@ -87,11 +89,10 @@
       pos_ += avail;
       pos_[0] = '\0';
       len -= avail;
-      total += avail;
     }
   }
 
-  int total;
+  size_t total;
 
  private:
   char* buffer_;
@@ -109,18 +110,19 @@
       len = strlen(data);
     }
 
+    total += len;
+
     while (len > 0) {
       int rc = TEMP_FAILURE_RETRY(write(fd_, data, len));
       if (rc == -1) {
-        break;
+        return;
       }
       data += rc;
       len -= rc;
-      total += rc;
     }
   }
 
-  int total;
+  size_t total;
 
  private:
   int fd_;
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
index 8df3bff..c93970a 100644
--- a/libc/bionic/pthread_attr.cpp
+++ b/libc/bionic/pthread_attr.cpp
@@ -116,6 +116,16 @@
 static int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_size) {
   ErrnoRestorer errno_restorer;
 
+  rlimit stack_limit;
+  if (getrlimit(RLIMIT_STACK, &stack_limit) == -1) {
+    return errno;
+  }
+
+  // If the current RLIMIT_STACK is RLIM_INFINITY, only admit to an 8MiB stack for sanity's sake.
+  if (stack_limit.rlim_cur == RLIM_INFINITY) {
+    stack_limit.rlim_cur = 8 * 1024 * 1024;
+  }
+
   // It doesn't matter which thread we are; we're just looking for "[stack]".
   FILE* fp = fopen("/proc/self/maps", "re");
   if (fp == NULL) {
@@ -126,17 +136,8 @@
     if (ends_with(line, " [stack]\n")) {
       uintptr_t lo, hi;
       if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &lo, &hi) == 2) {
-        *stack_base = reinterpret_cast<void*>(lo);
-        *stack_size = hi - lo;
-
-        // Does our current RLIMIT_STACK mean we won't actually get everything /proc/maps promises?
-        rlimit stack_limit;
-        if (getrlimit(RLIMIT_STACK, &stack_limit) != -1) {
-          if (*stack_size > stack_limit.rlim_cur) {
-            *stack_size = stack_limit.rlim_cur;
-          }
-        }
-
+        *stack_size = stack_limit.rlim_cur;
+        *stack_base = reinterpret_cast<void*>(hi - *stack_size);
         fclose(fp);
         return 0;
       }
diff --git a/libc/bionic/strerror_r.cpp b/libc/bionic/strerror_r.cpp
index 1e57cc0..d419fb1 100644
--- a/libc/bionic/strerror_r.cpp
+++ b/libc/bionic/strerror_r.cpp
@@ -1,11 +1,16 @@
 /* $OpenBSD: strerror_r.c,v 1.6 2005/08/08 08:05:37 espie Exp $ */
 /* Public Domain <marc@snafu.org> */
 
+// G++ automatically defines _GNU_SOURCE, which then means that <string.h>
+// gives us the GNU variant.
+#undef _GNU_SOURCE
+
+#include <string.h>
+
 #include <errno.h>
 #include <limits.h>
 #include <signal.h>
 #include <stdio.h>
-#include <string.h>
 
 #include "private/ErrnoRestorer.h"
 #include "private/libc_logging.h"
@@ -62,6 +67,12 @@
   return 0;
 }
 
+extern "C" char* __gnu_strerror_r(int error_number, char* buf, size_t buf_len) {
+  ErrnoRestorer errno_restorer; // The glibc strerror_r doesn't set errno if it truncates...
+  strerror_r(error_number, buf, buf_len);
+  return buf; // ...and just returns whatever fit.
+}
+
 extern "C" __LIBC_HIDDEN__ const char* __strsignal(int signal_number, char* buf, size_t buf_len) {
   const char* signal_name = __strsignal_lookup(signal_number);
   if (signal_name != NULL) {
diff --git a/libc/include/string.h b/libc/include/string.h
index 0a1d653..b0643af 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -67,8 +67,12 @@
 extern char*  strtok(char* __restrict, const char* __restrict);
 extern char*  strtok_r(char* __restrict, const char* __restrict, char** __restrict);
 
-extern char*  strerror(int);
-extern int    strerror_r(int errnum, char *buf, size_t n);
+extern char* strerror(int);
+#if defined(__USE_GNU)
+extern char* strerror_r(int, char*, size_t) __RENAME(__gnu_strerror_r);
+#else /* POSIX */
+extern int strerror_r(int, char*, size_t);
+#endif
 
 extern size_t strnlen(const char *, size_t) __purefunc;
 extern char*  strncat(char* __restrict, const char* __restrict, size_t);
diff --git a/linker/debugger.cpp b/linker/debugger.cpp
index 079682c..c316151 100644
--- a/linker/debugger.cpp
+++ b/linker/debugger.cpp
@@ -170,9 +170,9 @@
   if (info != NULL) {
     // For a rethrown signal, this si_code will be right and the one debuggerd shows will
     // always be SI_TKILL.
-    snprintf(code_desc, sizeof(code_desc), ", code %d", info->si_code);
+    __libc_format_buffer(code_desc, sizeof(code_desc), ", code %d", info->si_code);
     if (has_address) {
-      snprintf(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
+      __libc_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
     }
   }
   __libc_format_log(ANDROID_LOG_FATAL, "libc",
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 5f5823b..91ec49f 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -892,7 +892,21 @@
 }
 
 void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
-  snprintf(buffer, buffer_size, "%s:%s", kDefaultLdPaths[0], kDefaultLdPaths[1]);
+  // Use basic string manipulation calls to avoid snprintf.
+  // snprintf indirectly calls pthread_getspecific to get the size of a buffer.
+  // When debug malloc is enabled, this call returns 0. This in turn causes
+  // snprintf to do nothing, which causes libraries to fail to load.
+  // See b/17302493 for further details.
+  // Once the above bug is fixed, this code can be modified to use
+  // snprintf again.
+  size_t required_len = strlen(kDefaultLdPaths[0]) + strlen(kDefaultLdPaths[1]) + 2;
+  if (buffer_size < required_len) {
+    __libc_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: buffer len %zu, required len %zu",
+                 buffer_size, required_len);
+  }
+  char* end = stpcpy(buffer, kDefaultLdPaths[0]);
+  *end = ':';
+  strcpy(end + 1, kDefaultLdPaths[1]);
 }
 
 void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
diff --git a/tests/Android.mk b/tests/Android.mk
index 5179bfa..26014ac 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -95,6 +95,7 @@
     stdio_ext_test.cpp \
     stdlib_test.cpp \
     string_test.cpp \
+    string_posix_strerror_r_test.cpp \
     strings_test.cpp \
     stubs_test.cpp \
     sstream_test.cpp \
diff --git a/tests/libc_logging_test.cpp b/tests/libc_logging_test.cpp
index 950161e..d4ceded 100644
--- a/tests/libc_logging_test.cpp
+++ b/tests/libc_logging_test.cpp
@@ -176,3 +176,15 @@
   GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif // __BIONIC__
 }
+
+TEST(libc_logging, buffer_overrun) {
+#if defined(__BIONIC__)
+  char buf[BUFSIZ];
+  ASSERT_EQ(11, __libc_format_buffer(buf, sizeof(buf), "hello %s", "world"));
+  EXPECT_STREQ("hello world", buf);
+  ASSERT_EQ(11, __libc_format_buffer(buf, 8, "hello %s", "world"));
+  EXPECT_STREQ("hello w", buf);
+#else // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif // __BIONIC__
+}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 5f74e38..6557738 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -842,8 +842,7 @@
   EXPECT_EQ(stack_size, stack_size2);
 
   // What does /proc/self/maps' [stack] line say?
-  void* maps_stack_base = NULL;
-  size_t maps_stack_size = 0;
+  void* maps_stack_hi = NULL;
   FILE* fp = fopen("/proc/self/maps", "r");
   ASSERT_TRUE(fp != NULL);
   char line[BUFSIZ];
@@ -852,31 +851,25 @@
     char name[10];
     sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d %10s", &lo, &hi, name);
     if (strcmp(name, "[stack]") == 0) {
-      maps_stack_base = reinterpret_cast<void*>(lo);
-      maps_stack_size = hi - lo;
+      maps_stack_hi = reinterpret_cast<void*>(hi);
       break;
     }
   }
   fclose(fp);
 
-#if defined(__BIONIC__)
-  // bionic thinks that the stack base and size should correspond to the mapped region.
-  EXPECT_EQ(maps_stack_base, stack_base);
-  EXPECT_EQ(maps_stack_size, stack_size);
-#else
-  // glibc doesn't give the true extent for some reason.
-#endif
-
-  // Both bionic and glibc agree that the high address you can compute from the returned
-  // values should match what /proc/self/maps says.
-  void* stack_end = reinterpret_cast<uint8_t*>(stack_base) + stack_size;
-  void* maps_stack_end = reinterpret_cast<uint8_t*>(maps_stack_base) + maps_stack_size;
-  EXPECT_EQ(maps_stack_end, stack_end);
-
-  //
-  // What if the rlimit is smaller than the stack's current extent?
-  //
+  // The stack size should correspond to RLIMIT_STACK.
   rlimit rl;
+  ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
+  EXPECT_EQ(rl.rlim_cur, stack_size);
+
+  // The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
+  // Remember that the stack grows down (and is mapped in on demand), so the low address of the
+  // region isn't very interesting.
+  EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
+
+  //
+  // What if RLIMIT_STACK is smaller than the stack's current extent?
+  //
   rl.rlim_cur = rl.rlim_max = 1024; // 1KiB. We know the stack must be at least a page already.
   rl.rlim_max = RLIM_INFINITY;
   ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
@@ -889,7 +882,7 @@
   ASSERT_EQ(1024U, stack_size);
 
   //
-  // What if the rlimit isn't a whole number of pages?
+  // What if RLIMIT_STACK isn't a whole number of pages?
   //
   rl.rlim_cur = rl.rlim_max = 6666; // Not a whole number of pages.
   rl.rlim_max = RLIM_INFINITY;
diff --git a/tests/string_posix_strerror_r_test.cpp b/tests/string_posix_strerror_r_test.cpp
new file mode 100644
index 0000000..09cebfe
--- /dev/null
+++ b/tests/string_posix_strerror_r_test.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef _GNU_SOURCE
+
+// Old versions of glibc (like our current host prebuilt sysroot one) have
+// headers that don't work if you #undef _GNU_SOURCE, which makes it
+// impossible to build this test.
+#include <features.h>
+
+#if !defined(__GLIBC__)
+#include <string.h>
+
+#include <errno.h>
+#include <gtest/gtest.h>
+
+TEST(string, posix_strerror_r) {
+  char buf[256];
+
+  // Valid.
+  ASSERT_EQ(0, strerror_r(0, buf, sizeof(buf)));
+  ASSERT_STREQ("Success", buf);
+  ASSERT_EQ(0, strerror_r(1, buf, sizeof(buf)));
+  ASSERT_STREQ("Operation not permitted", buf);
+
+  // Invalid.
+  ASSERT_EQ(0, strerror_r(-1, buf, sizeof(buf)));
+  ASSERT_STREQ("Unknown error -1", buf);
+  ASSERT_EQ(0, strerror_r(1234, buf, sizeof(buf)));
+  ASSERT_STREQ("Unknown error 1234", buf);
+
+  // Buffer too small.
+  errno = 0;
+  memset(buf, 0, sizeof(buf));
+  ASSERT_EQ(-1, strerror_r(4567, buf, 2));
+  ASSERT_STREQ("U", buf);
+  // The POSIX strerror_r sets errno to ERANGE (the GNU one doesn't).
+  ASSERT_EQ(ERANGE, errno);
+}
+#else
+# if __GLIBC_PREREQ(2, 15)
+#  error this test should work now
+# endif
+#endif
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index a3c6abb..7db8e21 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define _GNU_SOURCE 1
+
 #include <string.h>
 
 #include <errno.h>
@@ -72,28 +74,34 @@
 #endif // __BIONIC__
 }
 
-TEST(string, strerror_r) {
-#if defined(__BIONIC__) // glibc's strerror_r doesn't even have the same signature as the POSIX one.
+TEST(string, gnu_strerror_r) {
   char buf[256];
 
+  // Note that glibc doesn't necessarily write into the buffer.
+
   // Valid.
-  ASSERT_EQ(0, strerror_r(0, buf, sizeof(buf)));
+  ASSERT_STREQ("Success", strerror_r(0, buf, sizeof(buf)));
+#if defined(__BIONIC__)
   ASSERT_STREQ("Success", buf);
-  ASSERT_EQ(0, strerror_r(1, buf, sizeof(buf)));
+#endif
+  ASSERT_STREQ("Operation not permitted", strerror_r(1, buf, sizeof(buf)));
+#if defined(__BIONIC__)
   ASSERT_STREQ("Operation not permitted", buf);
+#endif
 
   // Invalid.
-  ASSERT_EQ(0, strerror_r(-1, buf, sizeof(buf)));
+  ASSERT_STREQ("Unknown error -1", strerror_r(-1, buf, sizeof(buf)));
   ASSERT_STREQ("Unknown error -1", buf);
-  ASSERT_EQ(0, strerror_r(1234, buf, sizeof(buf)));
+  ASSERT_STREQ("Unknown error 1234", strerror_r(1234, buf, sizeof(buf)));
   ASSERT_STREQ("Unknown error 1234", buf);
 
   // Buffer too small.
-  ASSERT_EQ(-1, strerror_r(0, buf, 2));
-  ASSERT_EQ(ERANGE, errno);
-#else // __BIONIC__
-  GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif // __BIONIC__
+  errno = 0;
+  memset(buf, 0, sizeof(buf));
+  ASSERT_EQ(buf, strerror_r(4567, buf, 2));
+  ASSERT_STREQ("U", buf);
+  // The GNU strerror_r doesn't set errno (the POSIX one sets it to ERANGE).
+  ASSERT_EQ(0, errno);
 }
 
 TEST(string, strsignal) {