Merge "<fts.h>: fix fts_compar declaration for C23." into main
diff --git a/libc/Android.bp b/libc/Android.bp
index f13a76c..a5bc482 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -2110,6 +2110,12 @@
             enabled: false,
         },
         x86_64: {
+            asflags: [
+                // Statically choose the SSE2 memset_generic as memset for
+                // baremetal, where we do not have the dynamic function
+                // dispatch machinery.
+                "-Dmemset_generic=memset",
+            ],
             srcs: [
                 "arch-x86_64/string/sse2-memmove-slm.S",
                 "arch-x86_64/string/sse2-memset-slm.S",
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index cd96375..85e742c 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -185,6 +185,7 @@
                   /*load_bias = */ 0);
   __libc_init_mte_stack(/*stack_top = */ raw_args);
   __libc_init_scudo();
+  __libc_globals.mutate(__libc_init_malloc);
   __libc_init_profiling_handlers();
   __libc_init_fork_handler();
 
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 441d884..1e0ef14 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -41,6 +41,7 @@
 #include <platform/bionic/malloc.h>
 #include <private/ScopedPthreadMutexLocker.h>
 #include <private/bionic_config.h>
+#include <private/bionic_defs.h>
 
 #include "gwp_asan_wrappers.h"
 #include "heap_tagging.h"
@@ -358,3 +359,37 @@
 const MallocDispatch* NativeAllocatorDispatch() {
   return &__libc_malloc_default_dispatch;
 }
+
+#if !defined(LIBC_STATIC)
+void MallocInitImpl(libc_globals* globals);
+#endif
+
+// Initializes memory allocation framework.
+// This routine is called from __libc_init routines in libc_init_dynamic.cpp
+// and libc_init_static.cpp.
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+__LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals) {
+#if !defined(LIBC_STATIC)
+  MallocInitImpl(globals);
+#endif
+  const char* value = getenv("MALLOC_USE_APP_DEFAULTS");
+  if (value == nullptr || value[0] == '\0') {
+    return;
+  }
+
+  // Normal apps currently turn off zero init for performance reasons.
+  SetHeapZeroInitialize(false);
+
+  // Do not call mallopt directly since that will try and lock the globals
+  // data structure.
+  int retval;
+  auto dispatch_table = GetDispatchTable();
+  if (__predict_false(dispatch_table != nullptr)) {
+    retval = dispatch_table->mallopt(M_DECAY_TIME, 1);
+  } else {
+    retval = Malloc(mallopt)(M_DECAY_TIME, 1);
+  }
+  if (retval == 1) {
+    globals->decay_time_enabled = true;
+  }
+}
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 7b6d7d4..e2c6eb1 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -375,7 +375,7 @@
 extern "C" size_t __scudo_get_stack_depot_size();
 
 // Initializes memory allocation framework once per process.
-static void MallocInitImpl(libc_globals* globals) {
+void MallocInitImpl(libc_globals* globals) {
   char prop[PROP_VALUE_MAX];
   char* options = prop;
 
@@ -409,13 +409,6 @@
   }
 }
 
-// Initializes memory allocation framework.
-// This routine is called from __libc_init routines in libc_init_dynamic.cpp.
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
-__LIBC_HIDDEN__ void __libc_init_malloc(libc_globals* globals) {
-  MallocInitImpl(globals);
-}
-
 // =============================================================================
 // Functions to support dumping of native heap allocations using malloc debug.
 // =============================================================================
diff --git a/libc/include/paths.h b/libc/include/paths.h
index 7de9eaa..9116f4e 100644
--- a/libc/include/paths.h
+++ b/libc/include/paths.h
@@ -45,7 +45,7 @@
 #define _PATH_CONSOLE "/dev/console"
 
 /** Default shell search path. */
-#define _PATH_DEFPATH "/product/bin:/apex/com.android.runtime/bin:/apex/com.android.art/bin:/system_ext/bin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin"
+#define _PATH_DEFPATH "/product/bin:/apex/com.android.runtime/bin:/apex/com.android.art/bin:/apex/com.android.virt/bin:/system_ext/bin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin"
 
 /** Path to the directory containing device files. */
 #define _PATH_DEV "/dev/"
diff --git a/tests/Android.bp b/tests/Android.bp
index e2ac09a..51afa55 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -1124,7 +1124,7 @@
     defaults: [
         "bionic_unit_tests_defaults",
     ],
-    test_suites: ["device-tests"],
+    test_suites: ["general-tests"],
     data: [
         ":libdlext_test_runpath_zip_zipaligned",
         ":libdlext_test_zip_zipaligned",
@@ -1152,7 +1152,7 @@
         "libtest_simple_hwasan_nohwasan",
     ],
     header_libs: ["bionic_libc_platform_headers"],
-    test_suites: ["device-tests"],
+    test_suites: ["general-tests"],
 }
 
 cc_test {
@@ -1203,7 +1203,7 @@
         "testbinary_is_stack_mte_after_dlopen",
     ],
     header_libs: ["bionic_libc_platform_headers"],
-    test_suites: ["device-tests"],
+    test_suites: ["general-tests"],
 }
 
 cc_test {
@@ -1232,7 +1232,7 @@
         "memtag_stack_abi_test.cpp",
     ],
     header_libs: ["bionic_libc_platform_headers"],
-    test_suites: ["device-tests"],
+    test_suites: ["general-tests"],
 }
 
 cc_test {
@@ -1276,7 +1276,7 @@
     name: "bionic-unit-tests-static",
     gtest: false,
     defaults: ["bionic_tests_defaults"],
-    test_suites: ["device-tests"],
+    test_suites: ["general-tests"],
     host_supported: false,
 
     srcs: [
diff --git a/tests/cpu_target_features_test.cpp b/tests/cpu_target_features_test.cpp
index d773772..3458bca 100644
--- a/tests/cpu_target_features_test.cpp
+++ b/tests/cpu_target_features_test.cpp
@@ -54,3 +54,15 @@
   GTEST_SKIP() << "Not targeting an aarch64 architecture.";
 #endif
 }
+
+TEST(cpu_target_features, has_expected_arm_compiler_values) {
+#if defined(__arm__)
+  ExecTestHelper eth;
+  char* const argv[] = {nullptr};
+  const auto invocation = [&] { execvp("cpu-target-features", argv); };
+  eth.Run(invocation, 0, "(^|\n)__ARM_FEATURE_AES=1($|\n)");
+  eth.Run(invocation, 0, "(^|\n)__ARM_FEATURE_CRC32=1($|\n)");
+#else
+  GTEST_SKIP() << "Not targeting an arm architecture.";
+#endif
+}
diff --git a/tests/malloc_stress_test.cpp b/tests/malloc_stress_test.cpp
index 00f5919..210eb3a 100644
--- a/tests/malloc_stress_test.cpp
+++ b/tests/malloc_stress_test.cpp
@@ -57,7 +57,7 @@
       }
       // EAGAIN means there is nothing left to read when ANDROID_LOG_NONBLOCK is set.
       if (retval != -EAGAIN) {
-        printf("Failed to read log entry: %s\n", strerrordesc_np(retval));
+        printf("Failed to read log entry: %m");
       }
       break;
     }
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 8bd8bc6..37c1ef0 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -1779,3 +1779,32 @@
   GTEST_SKIP() << "bionic-only test";
 #endif
 }
+
+TEST(android_mallopt, DISABLED_verify_decay_time_on) {
+#if defined(__BIONIC__)
+  bool value;
+  EXPECT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
+  EXPECT_TRUE(value) << "decay time did not get enabled properly.";
+#endif
+}
+
+TEST(android_mallopt, decay_time_set_using_env_variable) {
+#if defined(__BIONIC__)
+  SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
+
+  bool value;
+  ASSERT_TRUE(android_mallopt(M_GET_DECAY_TIME_ENABLED, &value, sizeof(value)));
+  ASSERT_FALSE(value) << "decay time did not get disabled properly.";
+
+  // Verify that setting the environment variable here will be carried into
+  // fork'd and exec'd processes.
+  ASSERT_EQ(0, setenv("MALLOC_USE_APP_DEFAULTS", "1", 1));
+  ExecTestHelper eth;
+  eth.SetArgs({testing::internal::GetArgvs()[0].c_str(), "--gtest_also_run_disabled_tests",
+               "--gtest_filter=android_mallopt.DISABLED_verify_decay_time_on", nullptr});
+  eth.Run([&]() { execv(testing::internal::GetArgvs()[0].c_str(), eth.GetArgs()); }, 0,
+          R"(\[  PASSED  \] 1 test)");
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}