Merge "posix_spawn: always clear O_CLOEXEC for dup'ed fds."
diff --git a/docs/status.md b/docs/status.md
index 9521da8..bf246a6 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -50,7 +50,7 @@
 
 Current libc symbols: https://android.googlesource.com/platform/bionic/+/master/libc/libc.map.txt
 
-New libc functions in T (API level 32):
+New libc functions in T (API level 33):
   * `backtrace`, `backtrace_symbols`, `backtrace_symbols_fd` (`<execinfo.h>`).
   * New system call wrappers: `preadv2`, `preadv64v2`, `pwritev2`,
     `pwritev64v2`.
diff --git a/libc/async_safe/async_safe_log.cpp b/libc/async_safe/async_safe_log.cpp
index 8b2a32b..2380e68 100644
--- a/libc/async_safe/async_safe_log.cpp
+++ b/libc/async_safe/async_safe_log.cpp
@@ -251,6 +251,7 @@
     char sign = '\0';
     int width = -1;
     int prec = -1;
+    bool alternate = false;
     size_t bytelen = sizeof(int);
     int slen;
     char buffer[32]; /* temporary buffer used to format numbers */
@@ -293,6 +294,9 @@
       } else if (c == ' ' || c == '+') {
         sign = c;
         continue;
+      } else if (c == '#') {
+        alternate = true;
+        continue;
       }
       break;
     }
@@ -344,9 +348,6 @@
     if (c == 's') {
       /* string */
       str = va_arg(args, const char*);
-      if (str == nullptr) {
-        str = "(null)";
-      }
     } else if (c == 'c') {
       /* character */
       /* NOTE: char is promoted to int when passed through the stack */
@@ -357,6 +358,9 @@
       buffer[0] = '0';
       buffer[1] = 'x';
       format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x');
+    } else if (c == 'm') {
+      char buf[256];
+      str = strerror_r(errno, buf, sizeof(buf));
     } else if (c == 'd' || c == 'i' || c == 'o' || c == 'u' || c == 'x' || c == 'X') {
       /* integers - first read value from stack */
       uint64_t value;
@@ -388,8 +392,19 @@
         value = static_cast<uint64_t>((static_cast<int64_t>(value << shift)) >> shift);
       }
 
-      /* format the number properly into our buffer */
-      format_integer(buffer, sizeof(buffer), value, c);
+      if (alternate && value != 0 && (c == 'x' || c == 'o')) {
+        if (c == 'x') {
+          buffer[0] = '0';
+          buffer[1] = 'x';
+          format_integer(buffer + 2, sizeof(buffer) - 2, value, c);
+        } else {
+          buffer[0] = '0';
+          format_integer(buffer + 1, sizeof(buffer) - 1, value, c);
+        }
+      } else {
+        /* format the number properly into our buffer */
+        format_integer(buffer, sizeof(buffer), value, c);
+      }
     } else if (c == '%') {
       buffer[0] = '%';
       buffer[1] = '\0';
@@ -397,6 +412,10 @@
       __assert(__FILE__, __LINE__, "conversion specifier unsupported");
     }
 
+    if (str == nullptr) {
+      str = "(null)";
+    }
+
     /* if we are here, 'str' points to the content that must be
      * outputted. handle padding and alignment now */
 
diff --git a/tests/async_safe_test.cpp b/tests/async_safe_test.cpp
index 6c4758e..f52387e 100644
--- a/tests/async_safe_test.cpp
+++ b/tests/async_safe_test.cpp
@@ -64,6 +64,10 @@
   async_safe_format_buffer(buf, sizeof(buf), "a%ldb", 70000L);
   EXPECT_STREQ("a70000b", buf);
 
+  errno = EINVAL;
+  async_safe_format_buffer(buf, sizeof(buf), "a%mZ");
+  EXPECT_STREQ("aInvalid argumentZ", buf);
+
   async_safe_format_buffer(buf, sizeof(buf), "a%pb", reinterpret_cast<void*>(0xb0001234));
   EXPECT_STREQ("a0xb0001234b", buf);
 
@@ -97,6 +101,30 @@
   async_safe_format_buffer(buf, sizeof(buf), "a%03d:%d:%02dz", 5, 5, 5);
   EXPECT_STREQ("a005:5:05z", buf);
 
+  async_safe_format_buffer(buf, sizeof(buf), "a%#xZ", 34);
+  EXPECT_STREQ("a0x22Z", buf);
+
+  async_safe_format_buffer(buf, sizeof(buf), "a%#xZ", 0);
+  EXPECT_STREQ("a0Z", buf);
+
+  async_safe_format_buffer(buf, sizeof(buf), "a%#5xZ", 20);
+  EXPECT_STREQ("a 0x14Z", buf);
+
+  snprintf(buf, sizeof(buf), "a%#08.8xZ", 1);
+  EXPECT_STREQ("a0x00000001Z", buf);
+
+  async_safe_format_buffer(buf, sizeof(buf), "a%#oZ", 777);
+  EXPECT_STREQ("a01411Z", buf);
+
+  async_safe_format_buffer(buf, sizeof(buf), "a%#oZ", 0);
+  EXPECT_STREQ("a0Z", buf);
+
+  async_safe_format_buffer(buf, sizeof(buf), "a%#6oZ", 15);
+  EXPECT_STREQ("a   017Z", buf);
+
+  snprintf(buf, sizeof(buf), "a%#08.8oZ", 11);
+  EXPECT_STREQ("a00000013Z", buf);
+
   void* p = nullptr;
   async_safe_format_buffer(buf, sizeof(buf), "a%d,%pz", 5, p);
   EXPECT_STREQ("a5,0x0z", buf);
diff --git a/tests/cfi_test.cpp b/tests/cfi_test.cpp
index aa5b12f..1c45946 100644
--- a/tests/cfi_test.cpp
+++ b/tests/cfi_test.cpp
@@ -43,26 +43,36 @@
 // death tests shouldn't ever hit. (It's possible that a design where a
 // deathtest always declares its expected signals up front is a better one,
 // and maybe that's an interesting future direction for libbase.)
+//
+// We include SIGSEGV because there's a test that passes heap addresses to
+// __cfi_slowpath and we only map the executable code shadow as readable.
+// We don't always get SIGSEGV there though: if the heap allocation happens
+// to be close enough to an executable mapping that its shadow is in the
+// same page as the executable shadow, we'll get SIGILL/SIGTRAP.
 class cfi_test_DeathTest : public testing::Test {
  protected:
   void SetUp() override {
     struct sigaction64 action = {.sa_handler = SIG_DFL};
-    sigaction64(SIGSEGV, &action, &previous_sigsegv_);
     sigaction64(SIGILL, &action, &previous_sigill_);
+    sigaction64(SIGSEGV, &action, &previous_sigsegv_);
+    sigaction64(SIGTRAP, &action, &previous_sigtrap_);
   }
 
   void TearDown() override {
-    sigaction64(SIGILL, &previous_sigill_, nullptr);
+    sigaction64(SIGTRAP, &previous_sigtrap_, nullptr);
     sigaction64(SIGSEGV, &previous_sigsegv_, nullptr);
+    sigaction64(SIGILL, &previous_sigill_, nullptr);
   }
 
  private:
-  struct sigaction64 previous_sigsegv_;
   struct sigaction64 previous_sigill_;
+  struct sigaction64 previous_sigsegv_;
+  struct sigaction64 previous_sigtrap_;
 };
 
 static bool KilledByCfi(int status) {
-  return WIFSIGNALED(status) && (WTERMSIG(status) == SIGILL || WTERMSIG(status) == SIGSEGV);
+  return WIFSIGNALED(status) &&
+         (WTERMSIG(status) == SIGTRAP || WTERMSIG(status) == SIGILL || WTERMSIG(status) == SIGSEGV);
 }
 
 static void f() {}
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 0bf8775..e3664fd 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -258,6 +258,9 @@
   dlclose(handle);
 }
 
+// HWASan uses an ifunc to describe the location of its shadow memory,
+// so even though it's an unusual case, Android needs to support
+// "ifunc variables".
 TEST(dlfcn, ifunc_variable) {
   typedef const char* (*fn_ptr)();
 
diff --git a/tests/libs/dlopen_testlib_ifunc_variable_impl.cpp b/tests/libs/dlopen_testlib_ifunc_variable_impl.cpp
index 4b13eba..624ae74 100644
--- a/tests/libs/dlopen_testlib_ifunc_variable_impl.cpp
+++ b/tests/libs/dlopen_testlib_ifunc_variable_impl.cpp
@@ -43,11 +43,13 @@
 extern "C" const char* v1 = "unset";
 extern "C" const char* v2 = "set";
 
-extern "C" void* is_ctor_called_ifun() {
-  return g_flag == 0 ? &var_false : &var_true;
+typedef const char* (*fn_ptr)();
+
+extern "C" fn_ptr is_ctor_called_ifun() {
+  return (fn_ptr)(g_flag == 0 ? &var_false : &var_true);
 }
 
-extern "C" void* foo_ifunc() {
-   char* choice = getenv("IFUNC_CHOICE");
-   return choice == nullptr ? &v1 : &v2;
+extern "C" fn_ptr foo_ifunc() {
+  char* choice = getenv("IFUNC_CHOICE");
+  return (fn_ptr)(choice == nullptr ? &v1 : &v2);
 }