Merge "bionic: Adapt segment gap test for various page sizes" into main
diff --git a/libc/Android.bp b/libc/Android.bp
index 2141e67..107db88 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -624,10 +624,12 @@
         "upstream-openbsd/lib/libc/string/wcslcpy.c",
         "upstream-openbsd/lib/libc/string/wcswidth.c",
 
-        // This file is originally from OpenBSD, and benefits from
-        // being compiled with openbsd-compat.h.
-        // TODO: clean this up instead.
+        // These files are originally from OpenBSD,
+        // and benefit from being compiled with openbsd-compat.h.
+        // TODO: clean them up instead.
         "bionic/fts.c",
+        "stdio/vfprintf.cpp",
+        "stdio/vfwprintf.cpp",
     ],
 
     // Each architecture has optimized versions of some routines,
@@ -686,9 +688,11 @@
 
     local_include_dirs: [
         "private",
-        "upstream-openbsd/android/include",
         "stdio",
-        "upstream-openbsd/lib/libc/include",
+        "upstream-openbsd/android/include/",
+        "upstream-openbsd/lib/libc/gdtoa/",
+        "upstream-openbsd/lib/libc/include/",
+        "upstream-openbsd/lib/libc/stdio/",
     ],
 
     name: "libc_openbsd",
@@ -698,8 +702,6 @@
     name: "libc_openbsd_large_stack",
     defaults: ["libc_defaults"],
     srcs: [
-        "stdio/vfprintf.cpp",
-        "stdio/vfwprintf.cpp",
         "upstream-openbsd/lib/libc/string/memmem.c",
         "upstream-openbsd/lib/libc/string/strstr.c",
     ],
@@ -710,11 +712,7 @@
     ],
 
     local_include_dirs: [
-        "private",
         "upstream-openbsd/android/include/",
-        "upstream-openbsd/lib/libc/gdtoa/",
-        "upstream-openbsd/lib/libc/include/",
-        "upstream-openbsd/lib/libc/stdio/",
     ],
 }
 
@@ -2233,11 +2231,17 @@
 // NDK headers.
 // ========================================================
 
-versioned_ndk_headers {
+ndk_headers {
     name: "common_libc",
     from: "include",
     to: "",
+    srcs: ["include/**/*.h"],
     license: "NOTICE",
+    // These don't pass the bad verification we do because many of them are
+    // arch-specific, and they aren't necessarily independently includable.
+    // That's not much of a problem though, since C-incompaitibilities in the
+    // UAPI headers should run into problems long before they reach us.
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2257,10 +2261,6 @@
         "kernel/uapi/xen/**/*.h",
     ],
     license: "NOTICE",
-    // These don't pass the bad verification we do because many of them are
-    // arch-specific, and they aren't necessarily independently includable.
-    // That's not much of a problem though, since C-incompaitibilities in the
-    // UAPI headers should run into problems long before they reach us.
     skip_verification: true,
 }
 
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 7d4fdd7..8c5572e 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -88,7 +88,6 @@
 int     setregid:setregid(gid_t, gid_t)    lp64
 int     chroot(const char*)  all
 int     prctl(int, unsigned long, unsigned long, unsigned long, unsigned long) all
-long    __arch_prctl:arch_prctl(int, unsigned long) x86_64
 int     capget(cap_user_header_t header, cap_user_data_t data) all
 int     capset(cap_user_header_t header, const cap_user_data_t data) all
 int     sigaltstack(const stack_t*, stack_t*) all
@@ -366,6 +365,7 @@
 
 # x86-specific
 int     __set_thread_area:set_thread_area(void*) x86
+long arch_prctl(int, unsigned long) x86_64
 
 # vdso stuff.
 int __clock_getres:clock_getres(clockid_t, struct timespec*) all
diff --git a/libc/arch-x86_64/bionic/__set_tls.c b/libc/arch-x86_64/bionic/__set_tls.c
index 10fd36f..9460a03 100644
--- a/libc/arch-x86_64/bionic/__set_tls.c
+++ b/libc/arch-x86_64/bionic/__set_tls.c
@@ -27,11 +27,12 @@
  */
 
 #include <sys/cdefs.h>
-#include <asm/prctl.h>
-#include <stdint.h>
 
-extern int __arch_prctl(int, unsigned long);
+// ARCH_SET_FS is not exposed via <sys/prctl.h> or <linux/prctl.h>.
+#include <asm/prctl.h>
+
+extern int arch_prctl(int, unsigned long);
 
 __LIBC_HIDDEN__ int __set_tls(void* ptr) {
-  return __arch_prctl(ARCH_SET_FS, (uintptr_t) ptr);
+  return arch_prctl(ARCH_SET_FS, (unsigned long) ptr);
 }
diff --git a/libc/include/bits/pthread_types.h b/libc/include/bits/pthread_types.h
index f359696..e30c4c1 100644
--- a/libc/include/bits/pthread_types.h
+++ b/libc/include/bits/pthread_types.h
@@ -43,7 +43,6 @@
 #endif
 } pthread_attr_t;
 
-#if __ANDROID_API__ >= 24
 typedef struct {
 #if defined(__LP64__)
   int64_t __private[4];
@@ -51,11 +50,8 @@
   int32_t __private[8];
 #endif
 } pthread_barrier_t;
-#endif
 
-#if __ANDROID_API__ >= 24
 typedef int pthread_barrierattr_t;
-#endif
 
 typedef struct {
 #if defined(__LP64__)
@@ -91,7 +87,6 @@
 
 typedef long pthread_rwlockattr_t;
 
-#if __ANDROID_API__ >= 24
 typedef struct {
 #if defined(__LP64__)
   int64_t __private;
@@ -99,6 +94,5 @@
   int32_t __private[2];
 #endif
 } pthread_spinlock_t;
-#endif
 
 typedef long pthread_t;
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index c81028e..1e9a285 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -93,14 +93,12 @@
 /** Flag for splice(). */
 #define SPLICE_F_GIFT 8
 
-#if __ANDROID_API__ >= 26
 /** Flag for sync_file_range(). */
 #define SYNC_FILE_RANGE_WAIT_BEFORE 1
 /** Flag for sync_file_range(). */
 #define SYNC_FILE_RANGE_WRITE 2
 /** Flag for sync_file_range(). */
 #define SYNC_FILE_RANGE_WAIT_AFTER 4
-#endif
 
 /**
  * [creat(2)](https://man7.org/linux/man-pages/man2/creat.2.html)
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 21c3b36..5904519 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -76,6 +76,9 @@
  */
 void* _Nullable realloc(void* _Nullable __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
 
+// Remove the explicit guard once //external/giflib has been fixed so that it no
+// longer provides a conflicting definition: http://b/352784252
+#if __ANDROID_API__ >= 29
 /**
  * [reallocarray(3)](https://man7.org/linux/man-pages/man3/realloc.3.html) resizes
  * allocated memory on the heap.
@@ -88,6 +91,7 @@
  * (but see the notes for malloc()).
  */
 void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __wur __INTRODUCED_IN(29);
+#endif
 
 /**
  * [free(3)](https://man7.org/linux/man-pages/man3/free.3.html) deallocates
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 0163c07..33c637f 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -70,9 +70,7 @@
 
 #define PTHREAD_ONCE_INIT 0
 
-#if __ANDROID_API__ >= 24
 #define PTHREAD_BARRIER_SERIAL_THREAD (-1)
-#endif
 
 #if defined(__LP64__)
 #define PTHREAD_STACK_MIN 16384
@@ -246,26 +244,20 @@
 int pthread_rwlock_unlock(pthread_rwlock_t* _Nonnull __rwlock);
 int pthread_rwlock_wrlock(pthread_rwlock_t* _Nonnull __rwlock);
 
-#if __ANDROID_API__ >= 24
 int pthread_barrierattr_init(pthread_barrierattr_t* _Nonnull __attr) __INTRODUCED_IN(24);
 int pthread_barrierattr_destroy(pthread_barrierattr_t* _Nonnull __attr) __INTRODUCED_IN(24);
 int pthread_barrierattr_getpshared(const pthread_barrierattr_t* _Nonnull __attr, int* _Nonnull __shared) __INTRODUCED_IN(24);
 int pthread_barrierattr_setpshared(pthread_barrierattr_t* _Nonnull __attr, int __shared) __INTRODUCED_IN(24);
-#endif
 
-#if __ANDROID_API__ >= 24
 int pthread_barrier_init(pthread_barrier_t* _Nonnull __barrier, const pthread_barrierattr_t* _Nullable __attr, unsigned __count) __INTRODUCED_IN(24);
 int pthread_barrier_destroy(pthread_barrier_t* _Nonnull __barrier) __INTRODUCED_IN(24);
 int pthread_barrier_wait(pthread_barrier_t* _Nonnull __barrier) __INTRODUCED_IN(24);
-#endif
 
-#if __ANDROID_API__ >= 24
 int pthread_spin_destroy(pthread_spinlock_t* _Nonnull __spinlock) __INTRODUCED_IN(24);
 int pthread_spin_init(pthread_spinlock_t* _Nonnull __spinlock, int __shared) __INTRODUCED_IN(24);
 int pthread_spin_lock(pthread_spinlock_t* _Nonnull __spinlock) __INTRODUCED_IN(24);
 int pthread_spin_trylock(pthread_spinlock_t* _Nonnull __spinlock) __INTRODUCED_IN(24);
 int pthread_spin_unlock(pthread_spinlock_t* _Nonnull __spinlock) __INTRODUCED_IN(24);
-#endif
 
 pthread_t pthread_self(void) __attribute_const__;
 
diff --git a/libc/include/spawn.h b/libc/include/spawn.h
index 3ce402f..f366239 100644
--- a/libc/include/spawn.h
+++ b/libc/include/spawn.h
@@ -46,14 +46,17 @@
 #define POSIX_SPAWN_USEVFORK 64
 #define POSIX_SPAWN_SETSID 128
 #endif
-// mark all fds (except stdin/out/err) as close-on-exec prior to executing registered file actions
+/**
+ * Used with posix_spawnattr_setflags() to mark all fds except
+ * stdin/stdout/stderr as O_CLOEXEC prior to executing registered file actions.
+ */
 #define POSIX_SPAWN_CLOEXEC_DEFAULT 256
 
 typedef struct __posix_spawnattr* posix_spawnattr_t;
 typedef struct __posix_spawn_file_actions* posix_spawn_file_actions_t;
 
-int posix_spawn(pid_t* _Nullable __pid, const char* _Nonnull __path, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nonnull __argv[_Nonnull], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
-int posix_spawnp(pid_t* _Nullable __pid, const char* _Nonnull __file, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nonnull __argv[_Nonnull], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
+int posix_spawn(pid_t* _Nullable __pid, const char* _Nonnull __path, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nullable __argv[_Nullable], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
+int posix_spawnp(pid_t* _Nullable __pid, const char* _Nonnull __file, const posix_spawn_file_actions_t _Nullable * _Nullable __actions, const posix_spawnattr_t _Nullable * _Nullable __attr, char* const _Nullable __argv[_Nullable], char* const _Nullable __env[_Nullable]) __INTRODUCED_IN(28);
 
 int posix_spawnattr_init(posix_spawnattr_t _Nullable * _Nonnull __attr) __INTRODUCED_IN(28);
 int posix_spawnattr_destroy(posix_spawnattr_t _Nonnull * _Nonnull __attr) __INTRODUCED_IN(28);
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 7c376d0..d2f3a65 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -75,7 +75,16 @@
 
 int posix_memalign(void* _Nullable * _Nullable __memptr, size_t __alignment, size_t __size);
 
-void* _Nullable aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
+/**
+ * [aligned_alloc(3)](https://man7.org/linux/man-pages/man3/aligned_alloc.3.html)
+ * allocates the given number of bytes with the given alignment.
+ *
+ * Returns a pointer to the allocated memory on success and returns a null
+ * pointer and sets `errno` on failure.
+ *
+ * Available since API level 28.
+ */
+__wur void* _Nullable aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
 
 double strtod(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr);
 long double strtold(const char* _Nonnull __s, char* _Nullable * _Nullable __end_ptr);
diff --git a/libc/stdio/printf_common.h b/libc/stdio/printf_common.h
index 702f8d3..653bba2 100644
--- a/libc/stdio/printf_common.h
+++ b/libc/stdio/printf_common.h
@@ -85,6 +85,10 @@
 // Helper function for `fprintf to unbuffered unix file': creates a
 // temporary buffer.  We only work on write-only files; this avoids
 // worries about ungetc buffers and so forth.
+//
+// We prevent inlining because this massively increases the printf()
+// family's stack usage to support a rare case.
+__attribute__((__noinline__))
 static int __sbprintf(FILE* fp, const CHAR_TYPE* fmt, va_list ap) {
   FILE fake;
   struct __sfileext fakeext;
diff --git a/libc/stdio/vfprintf.cpp b/libc/stdio/vfprintf.cpp
index e0509aa..354317c 100644
--- a/libc/stdio/vfprintf.cpp
+++ b/libc/stdio/vfprintf.cpp
@@ -43,7 +43,7 @@
 
 #define PRINT(ptr, len)                          \
   do {                                           \
-    iovp->iov_base = (ptr);                      \
+    iovp->iov_base = (void*)(ptr);               \
     iovp->iov_len = (len);                       \
     uio.uio_resid += (len);                      \
     iovp++;                                      \
@@ -125,10 +125,10 @@
    * below longer.
    */
 #define PADSIZE 16 /* pad chunk size */
-  static CHAR_TYPE blanks[PADSIZE] = {
+  static const CHAR_TYPE blanks[PADSIZE] = {
     ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
   };
-  static CHAR_TYPE zeroes[PADSIZE] = {
+  static const CHAR_TYPE zeroes[PADSIZE] = {
     '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
   };
 
diff --git a/libc/stdio/vfwprintf.cpp b/libc/stdio/vfwprintf.cpp
index 72f973c..89e889e 100644
--- a/libc/stdio/vfwprintf.cpp
+++ b/libc/stdio/vfwprintf.cpp
@@ -128,10 +128,10 @@
    * below longer.
    */
 #define PADSIZE 16 /* pad chunk size */
-  static CHAR_TYPE blanks[PADSIZE] = {
+  static const CHAR_TYPE blanks[PADSIZE] = {
     ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
   };
-  static CHAR_TYPE zeroes[PADSIZE] = {
+  static const CHAR_TYPE zeroes[PADSIZE] = {
     '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'
   };
 
diff --git a/libc/system_properties/Android.bp b/libc/system_properties/Android.bp
index 16ea73f..e2fce34 100644
--- a/libc/system_properties/Android.bp
+++ b/libc/system_properties/Android.bp
@@ -58,27 +58,10 @@
     ],
 }
 
-soong_config_module_type {
-    name: "large_system_property_node_cc_defaults",
-    module_type: "cc_defaults",
-    config_namespace: "bionic",
-    bool_variables: [
-        "large_system_property_node",
-    ],
-    properties: [
-        "cflags",
-    ],
-}
-
-soong_config_bool_variable {
-    name: "large_system_property_node",
-}
-
-large_system_property_node_cc_defaults {
+cc_defaults {
     name: "large_system_property_node_defaults",
-    soong_config_variables: {
-        large_system_property_node: {
-            cflags: ["-DLARGE_SYSTEM_PROPERTY_NODE=1"]
-        }
-    }
+    cflags: select(release_flag("RELEASE_LARGE_SYSTEM_PROPERTY_NODE"), {
+        true: ["-DLARGE_SYSTEM_PROPERTY_NODE=1"],
+        default: [],
+    }),
 }
diff --git a/libc/tzcode/strptime.c b/libc/tzcode/strptime.c
index 5f91e46..20160c9 100644
--- a/libc/tzcode/strptime.c
+++ b/libc/tzcode/strptime.c
@@ -68,8 +68,8 @@
 #define FIELD_TM_YDAY	(1 << 3)
 #define FIELD_TM_YEAR	(1 << 4)
 
-static char gmt[] = { "GMT" };
-static char utc[] = { "UTC" };
+static const char gmt[] = { "GMT" };
+static const char utc[] = { "UTC" };
 /* RFC-822/RFC-2822 */
 static const char * const nast[5] = {
        "EST",    "CST",    "MST",    "PST",    "\0\0\0"
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 0e5fb96..86b6509 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -250,12 +250,6 @@
   return result;
 }
 
-#if defined(__LP64__)
-static char kFallbackLinkerPath[] = "/system/bin/linker64";
-#else
-static char kFallbackLinkerPath[] = "/system/bin/linker";
-#endif
-
 // Load an executable. Normally the kernel has already loaded the executable when the linker
 // starts. The linker can be invoked directly on an executable, though, and then the linker must
 // load it. This function doesn't load dependencies or resolve relocations.
@@ -380,7 +374,12 @@
   if (interp == nullptr) {
     // This case can happen if the linker attempts to execute itself
     // (e.g. "linker64 /system/bin/linker64").
-    interp = kFallbackLinkerPath;
+#if defined(__LP64__)
+#define DEFAULT_INTERP "/system/bin/linker64"
+#else
+#define DEFAULT_INTERP "/system/bin/linker"
+#endif
+    interp = DEFAULT_INTERP;
   }
   solinker->set_realpath(interp);
   init_link_map_head(*solinker);
diff --git a/tests/mntent_test.cpp b/tests/mntent_test.cpp
index 4b8fc9a..fd69ae1 100644
--- a/tests/mntent_test.cpp
+++ b/tests/mntent_test.cpp
@@ -59,9 +59,7 @@
   // indices                  1  1
   // of keys:      0    5   9 1  4
   char mnt_opts[]{"aa=b,a=b,b,bb,c=d"};
-  struct mntent ent;
-  memset(&ent, 0, sizeof(ent));
-  ent.mnt_opts = mnt_opts;
+  struct mntent ent = {.mnt_opts = mnt_opts};
 
   EXPECT_EQ(mnt_opts, hasmntopt(&ent, "aa"));
   EXPECT_EQ(mnt_opts + 5, hasmntopt(&ent, "a"));
@@ -71,3 +69,9 @@
   EXPECT_EQ(nullptr, hasmntopt(&ent, "d"));
   EXPECT_EQ(nullptr, hasmntopt(&ent, "e"));
 }
+
+TEST(mntent, hasmntopt_no_suffix_match) {
+  char mnt_opts[]{"noatime"};
+  struct mntent ent = {.mnt_opts = mnt_opts};
+  EXPECT_EQ(nullptr, hasmntopt(&ent, "atime"));
+}