Merge "Add a test for a recent POSIX change."
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index be21e0c..230899a 100644
--- a/libc/bionic/heap_tagging.cpp
+++ b/libc/bionic/heap_tagging.cpp
@@ -208,6 +208,9 @@
   }
 #endif  // __aarch64__
 
+  // We can use __has_feature here rather than __hwasan_handle_longjmp as a
+  // weak symbol because this is part of libc which is always sanitized for a
+  // hwasan enabled process.
 #if __has_feature(hwaddress_sanitizer)
   __hwasan_handle_longjmp(sp_dst);
 #endif  // __has_feature(hwaddress_sanitizer)
diff --git a/libc/include/time.h b/libc/include/time.h
index 08f30ef..31c2050 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -42,7 +42,13 @@
 /* If we just use void* in the typedef, the compiler exposes that in error messages. */
 struct __timezone_t;
 
-/** The `timezone_t` type that represents a timezone. */
+/**
+ * The `timezone_t` type that represents a timezone.
+ *
+ * To use this with std::unique_ptr you'll want something like
+ * `std::unique_ptr<std::remove_pointer_t<timezone_t>, decltype(&tzfree)> tz{tzalloc("Asia/Seoul"), tzfree};`
+ * to remove the pointer.
+ */
 typedef struct __timezone_t* timezone_t;
 
 /** Divisor to compute seconds from the result of a call to clock(). */
@@ -300,6 +306,10 @@
  * tzalloc() is thread safe (though obviously the system timezone can
  * change, especially if your mobile device is actually mobile!).
  *
+ * To use this with std::unique_ptr you'll want something like
+ * `std::unique_ptr<std::remove_pointer_t<timezone_t>, decltype(&tzfree)> tz{tzalloc("Asia/Seoul"), tzfree};`
+ * to remove the pointer.
+ *
  * Returns a timezone object on success, and returns NULL and sets `errno` on failure.
  *
  * Available since API level 35.
@@ -309,6 +319,10 @@
 /**
  * tzfree(3) frees a timezone object returned by tzalloc().
  *
+ * To use this with std::unique_ptr you'll want something like
+ * `std::unique_ptr<std::remove_pointer_t<timezone_t>, decltype(&tzfree)> tz{tzalloc("Asia/Seoul"), tzfree};`
+ * to remove the pointer.
+ *
  * Available since API level 35.
  */
 void tzfree(timezone_t _Nullable __tz) __INTRODUCED_IN(35);
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 98fab52..9385264 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -302,7 +302,7 @@
 
 int acct(const char* _Nullable __path);
 
-int getpagesize(void);
+int getpagesize(void) __attribute_const__;
 
 long syscall(long __number, ...);
 
diff --git a/tests/heap_tagging_level_test.cpp b/tests/heap_tagging_level_test.cpp
index 917be37..5d85e97 100644
--- a/tests/heap_tagging_level_test.cpp
+++ b/tests/heap_tagging_level_test.cpp
@@ -221,6 +221,8 @@
 enum class MemtagNote { NONE, ASYNC, SYNC };
 class MemtagNoteTest : public testing::TestWithParam<std::tuple<MemtagNote, bool>> {};
 
+static const char* kNoteSuffix[] = {"disabled", "async", "sync"};
+
 TEST_P(MemtagNoteTest, SEGV) {
 #if defined(__BIONIC__) && defined(__aarch64__)
   SKIP_WITH_NATIVE_BRIDGE;  // http://b/242170715
@@ -229,19 +231,13 @@
   }
   // Note that we do not check running_with_hwasan() - what matters here is whether the test binary
   // itself is built with HWASan.
-  bool withHWASAN = __has_feature(hwaddress_sanitizer);
   bool withMTE = getauxval(AT_HWCAP2) & HWCAP2_MTE;
 
-  const char* kNoteSuffix[] = {"disabled", "async", "sync"};
-  const char* kExpectedOutputHWASAN[] = {".*tag-mismatch.*", ".*tag-mismatch.*",
-                                         ".*tag-mismatch.*"};
   // Note that we do not check the exact si_code of the "async" variant, as it may be auto-upgraded
   // to asymm or even sync.
   const char* kExpectedOutputMTE[] = {"normal exit\n", "SEGV_MTE[AS]ERR\n", "SEGV_MTESERR\n"};
   const char* kExpectedOutputNonMTE[] = {"normal exit\n", "normal exit\n", "normal exit\n"};
-  const char** kExpectedOutput =
-      withHWASAN ? kExpectedOutputHWASAN : (withMTE ? kExpectedOutputMTE : kExpectedOutputNonMTE);
-  const int kExpectedExitStatus = withHWASAN ? -SIGABRT : 0;
+  const char** kExpectedOutput = withMTE ? kExpectedOutputMTE : kExpectedOutputNonMTE;
 
   MemtagNote note = std::get<0>(GetParam());
   bool isStatic = std::get<1>(GetParam());
@@ -251,7 +247,7 @@
   chmod(helper.c_str(), 0755);
   ExecTestHelper eth;
   eth.SetArgs({helper.c_str(), nullptr});
-  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, kExpectedExitStatus,
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0,
           kExpectedOutput[static_cast<int>(note)]);
 #else
   GTEST_SKIP() << "bionic/arm64 only";
@@ -261,4 +257,10 @@
 INSTANTIATE_TEST_SUITE_P(, MemtagNoteTest,
                          testing::Combine(testing::Values(MemtagNote::NONE, MemtagNote::ASYNC,
                                                           MemtagNote::SYNC),
-                                          testing::Bool()));
+                                          testing::Bool()),
+                         [](const ::testing::TestParamInfo<MemtagNoteTest::ParamType>& info) {
+                           MemtagNote note = std::get<0>(info.param);
+                           std::string s = kNoteSuffix[static_cast<int>(note)];
+                           if (std::get<1>(info.param)) s += "_static";
+                           return s;
+                         });
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index a2fbe55..51f5ac6 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -1621,6 +1621,7 @@
      diag: {
        memtag_heap: true,
      },
+     hwaddress: false,
    },
 }
 
@@ -1633,6 +1634,7 @@
      diag: {
        memtag_heap: false,
      },
+     hwaddress: false,
    },
 }
 
@@ -1642,6 +1644,7 @@
    srcs: ["heap_tagging_helper.cpp"],
    sanitize: {
      memtag_heap: false,
+     hwaddress: false,
    },
 }
 
@@ -1655,6 +1658,7 @@
      diag: {
        memtag_heap: true,
      },
+     hwaddress: false,
    },
 }
 
@@ -1668,6 +1672,7 @@
      diag: {
        memtag_heap: false,
      },
+     hwaddress: false,
    },
 }
 
@@ -1678,6 +1683,7 @@
    static_executable: true,
    sanitize: {
      memtag_heap: false,
+     hwaddress: false,
    },
 }
 
@@ -1691,6 +1697,7 @@
      diag: {
        memtag_heap: true,
      },
+     hwaddress: false,
    },
    header_libs: ["bionic_libc_platform_headers"],
    cflags: ["-fexceptions"],
@@ -1707,6 +1714,7 @@
      diag: {
        memtag_heap: true,
      },
+     hwaddress: false,
    },
    header_libs: ["bionic_libc_platform_headers"],
    cflags: ["-fexceptions"],
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index abf6ce0..ec59aa7 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -1452,3 +1452,12 @@
   GTEST_SKIP() << "glibc doesn't have timezone_t";
 #endif
 }
+
+TEST(time, tzalloc_unique_ptr) {
+#if __BIONIC__
+  std::unique_ptr<std::remove_pointer_t<timezone_t>, decltype(&tzfree)> tz{tzalloc("Asia/Seoul"),
+                                                                           tzfree};
+#else
+  GTEST_SKIP() << "glibc doesn't have timezone_t";
+#endif
+}