Merge "libc: suppress libcxx's const-correct string overloads" into main
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index ef41e2d..0163c07 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -144,20 +144,7 @@
                                         const struct timespec* _Nullable __timeout) __INTRODUCED_IN_64(28);
 int pthread_cond_wait(pthread_cond_t* _Nonnull __cond, pthread_mutex_t* _Nonnull __mutex);
 
-#if defined(__clang__)
-/*
- * Disable -Wbuiltin-requires-header because clang confuses this declaration with the one defined in
- * "llvm/tools/clang/include/clang/Basic/Builtins.def", which did not define any formal arguments.
- * It seems to be an upstream bug and the fix (https://reviews.llvm.org/D58531) is still under
- * review. Thus, let's disable the warning for this function declaration.
- */
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wbuiltin-requires-header"
-#endif
 int pthread_create(pthread_t* _Nonnull __pthread_ptr, pthread_attr_t const* _Nullable __attr, void* _Nonnull (* _Nonnull __start_routine)(void* _Nonnull), void* _Nullable);
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
 
 int pthread_detach(pthread_t __pthread);
 void pthread_exit(void* _Nullable __return_value) __noreturn;
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index ff3d498..e89acb5 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -567,9 +567,7 @@
       continue;
     }
 
-    if (phdr->p_align > maximum_alignment) {
-      maximum_alignment = phdr->p_align;
-    }
+    maximum_alignment = std::max(maximum_alignment, static_cast<size_t>(phdr->p_align));
   }
 
 #if defined(__LP64__)
@@ -579,6 +577,30 @@
 #endif
 }
 
+// Returns the minimum p_align associated with a loadable segment in the ELF
+// program header table. Used to determine if the program alignment is compatible
+// with the page size of this system.
+size_t phdr_table_get_minimum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count) {
+  size_t minimum_alignment = page_size();
+
+  for (size_t i = 0; i < phdr_count; ++i) {
+    const ElfW(Phdr)* phdr = &phdr_table[i];
+
+    // p_align must be 0, 1, or a positive, integral power of two.
+    if (phdr->p_type != PT_LOAD || ((phdr->p_align & (phdr->p_align - 1)) != 0)) {
+      continue;
+    }
+
+    if (phdr->p_align <= 1) {
+      continue;
+    }
+
+    minimum_alignment = std::min(minimum_alignment, static_cast<size_t>(phdr->p_align));
+  }
+
+  return minimum_alignment;
+}
+
 // Reserve a virtual address range such that if it's limits were extended to the next 2**align
 // boundary, it would not overlap with any existing mappings.
 static void* ReserveWithAlignmentPadding(size_t size, size_t mapping_align, size_t start_align,
@@ -830,6 +852,15 @@
 }
 
 bool ElfReader::LoadSegments() {
+  size_t min_palign = phdr_table_get_minimum_alignment(phdr_table_, phdr_num_);
+  // Only enforce this on 16 KB systems. Apps may rely on undefined behavior
+  // here on 4 KB systems, which is the norm before this change is introduced.
+  if (kPageSize >= 16384 && min_palign < kPageSize) {
+    DL_ERR("\"%s\" program alignment (%zu) cannot be smaller than system page size (%zu)",
+           name_.c_str(), min_palign, kPageSize);
+    return false;
+  }
+
   for (size_t i = 0; i < phdr_num_; ++i) {
     const ElfW(Phdr)* phdr = &phdr_table_[i];
 
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index aab9018..e865a03 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -126,6 +126,7 @@
                                 ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr);
 
 size_t phdr_table_get_maximum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count);
+size_t phdr_table_get_minimum_alignment(const ElfW(Phdr)* phdr_table, size_t phdr_count);
 
 int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                 ElfW(Addr) load_bias, bool should_pad_segments,
diff --git a/tests/Android.bp b/tests/Android.bp
index d2a3110..cfaeced 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -719,11 +719,6 @@
     ],
     srcs: ["clang_fortify_tests.cpp"],
     tidy: false,
-    target: {
-        host: {
-            cflags: ["-D__clang__"],
-        },
-    },
 }
 
 cc_test_library {
diff --git a/tests/clang_fortify_tests.cpp b/tests/clang_fortify_tests.cpp
index f4ef4ac..f08fd1f 100644
--- a/tests/clang_fortify_tests.cpp
+++ b/tests/clang_fortify_tests.cpp
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-#ifndef __clang__
-#error "Non-clang isn't supported"
-#endif
-
 //
 // Clang compile-time and run-time tests for Bionic's FORTIFY.
 //
diff --git a/tests/headers/posix/stdlib_h.c b/tests/headers/posix/stdlib_h.c
index 52580cf..95769b4 100644
--- a/tests/headers/posix/stdlib_h.c
+++ b/tests/headers/posix/stdlib_h.c
@@ -112,6 +112,9 @@
   FUNCTION(ptsname, char* (*f)(int));
   FUNCTION(putenv, int (*f)(char*));
   FUNCTION(qsort, void (*f)(void*, size_t, size_t, int (*)(const void*, const void*)));
+#if !defined(__GLIBC__) // Our glibc is too old.
+  FUNCTION(qsort_r, void (*f)(void*, size_t, size_t, int (*)(const void*, const void*, void*), void*));
+#endif
   FUNCTION(rand, int (*f)(void));
   FUNCTION(rand_r, int (*f)(unsigned*));
   FUNCTION(random, long (*f)(void));
diff --git a/tests/headers/posix/unistd_h.c b/tests/headers/posix/unistd_h.c
index 0b2cee5..f66609d 100644
--- a/tests/headers/posix/unistd_h.c
+++ b/tests/headers/posix/unistd_h.c
@@ -331,6 +331,9 @@
   FUNCTION(fdatasync, int (*f)(int));
   FUNCTION(fexecve, int (*f)(int, char* const[], char* const[]));
   FUNCTION(fork, pid_t (*f)(void));
+#if !defined(__GLIBC__) // Our glibc is too old.
+  FUNCTION(_Fork, pid_t (*f)(void));
+#endif
   FUNCTION(fpathconf, long (*f)(int, int));
   FUNCTION(fsync, int (*f)(int));
   FUNCTION(ftruncate, int (*f)(int, off_t));