Merge "libc.map.txt: remove the two riscv64 special cases." into main
diff --git a/docs/status.md b/docs/status.md
index 7ebd195..0436c40 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -55,6 +55,9 @@
 
 Current libc symbols: https://android.googlesource.com/platform/bionic/+/main/libc/libc.map.txt
 
+New libc functions in API level 36:
+  * `qsort_r` (new POSIX addition).
+
 New libc functions in V (API level 35):
   * New `android_crash_detail_register`, `android_crash_detail_unregister`,
     `android_crash_detail_replace_name`, and `android_crash_detail_replace_data`
diff --git a/libc/Android.bp b/libc/Android.bp
index 79b85c5..42ffd37 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -389,6 +389,7 @@
         "upstream-freebsd/lib/libc/stdlib/hdestroy_r.c",
         "upstream-freebsd/lib/libc/stdlib/hsearch_r.c",
         "upstream-freebsd/lib/libc/stdlib/qsort.c",
+        "upstream-freebsd/lib/libc/stdlib/qsort_r.c",
         "upstream-freebsd/lib/libc/stdlib/quick_exit.c",
         "upstream-freebsd/lib/libc/string/wcpcpy.c",
         "upstream-freebsd/lib/libc/string/wcpncpy.c",
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index e50fca0..ba20c51 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -118,12 +118,15 @@
 
 static void __init_shadow_call_stack(pthread_internal_t* thread __unused) {
 #if defined(__aarch64__) || defined(__riscv)
-  // Allocate the stack and the guard region.
+  // Allocate the shadow call stack and its guard region.
   char* scs_guard_region = reinterpret_cast<char*>(
-      mmap(nullptr, SCS_GUARD_REGION_SIZE, 0, MAP_PRIVATE | MAP_ANON, -1, 0));
+      mmap(nullptr, SCS_GUARD_REGION_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0));
+  if (scs_guard_region == MAP_FAILED) {
+    async_safe_fatal("failed to allocate shadow stack: %m");
+  }
   thread->shadow_call_stack_guard_region = scs_guard_region;
 
-  // The address is aligned to SCS_SIZE so that we only need to store the lower log2(SCS_SIZE) bits
+  // Align the address to SCS_SIZE so that we only need to store the lower log2(SCS_SIZE) bits
   // in jmp_buf. See the SCS commentary in pthread_internal.h for more detail.
   char* scs_aligned_guard_region =
       reinterpret_cast<char*>(align_up(reinterpret_cast<uintptr_t>(scs_guard_region), SCS_SIZE));
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index d0efc4c..b160e6b 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -114,7 +114,20 @@
  */
 __wur void* _Nullable bsearch(const void* _Nonnull __key, const void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull __lhs, const void* _Nonnull __rhs));
 
-void qsort(void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nullable __lhs, const void* _Nullable __rhs));
+/**
+ * [qsort(3)](http://man7.org/linux/man-pages/man3/qsort.3.html) sorts an array
+ * of n elements each of the given size, using the given comparator.
+ */
+void qsort(void* _Nullable __array, size_t __n, size_t __size, int (* _Nonnull __comparator)(const void* _Nullable __lhs, const void* _Nullable __rhs));
+
+/**
+ * [qsort_r(3)](http://man7.org/linux/man-pages/man3/qsort_r.3.html) sorts an
+ * array of n elements each of the given size, using the given comparator,
+ * and passing the given context argument to the comparator.
+ *
+ * Available since API level 36.
+ */
+void qsort_r(void* _Nullable __array, size_t __n, size_t __size, int (* _Nonnull __comparator)(const void* _Nullable __lhs, const void* _Nullable __rhs, void* _Nullable __context), void* _Nullable __context) __INTRODUCED_IN(36);
 
 uint32_t arc4random(void);
 uint32_t arc4random_uniform(uint32_t __upper_bound);
diff --git a/libc/include/sys/_system_properties.h b/libc/include/sys/_system_properties.h
index 078e857..05612b3 100644
--- a/libc/include/sys/_system_properties.h
+++ b/libc/include/sys/_system_properties.h
@@ -26,8 +26,7 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _INCLUDE_SYS__SYSTEM_PROPERTIES_H
-#define _INCLUDE_SYS__SYSTEM_PROPERTIES_H
+#pragma once
 
 #include <sys/cdefs.h>
 #include <stdint.h>
@@ -40,13 +39,67 @@
 
 __BEGIN_DECLS
 
+/**
+ * Reads the global serial number of the system properties _area_.
+ *
+ * Called to predict if a series of cached __system_property_find()
+ * objects will have seen __system_property_serial() values change.
+ * Also aids the converse, as changes in the global serial can
+ * also be used to predict if a failed __system_property_find()
+ * could in turn now find a new object; thus preventing the
+ * cycles of effort to poll __system_property_find().
+ *
+ * Typically called at beginning of a cache cycle to signal if _any_ possible
+ * changes have occurred since last. If there is, one may check each individual
+ * __system_property_serial() to confirm dirty, or __system_property_find()
+ * to check if the property now exists. If a call to __system_property_add()
+ * or __system_property_update() has completed between two calls to
+ * __system_property_area_serial() then the second call will return a larger
+ * value than the first call. Beware of race conditions as changes to the
+ * properties are not atomic, the main value of this call is to determine
+ * whether the expensive __system_property_find() is worth retrying to see if
+ * a property now exists.
+ *
+ * Returns the serial number on success, -1 on error.
+ */
+uint32_t __system_property_area_serial(void);
+
+/**
+ * Reads the serial number of a specific system property previously returned by
+ * __system_property_find(). This is a cheap way to check whether a system
+ * property has changed or not.
+ *
+ * Returns the serial number on success, -1 on error.
+ */
+uint32_t __system_property_serial(const prop_info* _Nonnull __pi);
+
+//
+// libc implementation detail.
+//
+
+/**
+ * Initializes the system properties area in read-only mode.
+ *
+ * This is called automatically during libc initialization,
+ * so user code should never need to call this.
+ *
+ * Returns 0 on success, -1 otherwise.
+ */
+int __system_properties_init(void);
+
+//
+// init implementation details.
+//
+
 #define PROP_SERVICE_NAME "property_service"
 #define PROP_SERVICE_FOR_SYSTEM_NAME "property_service_for_system"
 #define PROP_DIRNAME "/dev/__properties__"
 
+// Messages sent to init.
 #define PROP_MSG_SETPROP 1
 #define PROP_MSG_SETPROP2 0x00020001
 
+// Status codes returned by init (but not passed from libc to the caller).
 #define PROP_SUCCESS 0
 #define PROP_ERROR_READ_CMD 0x0004
 #define PROP_ERROR_READ_DATA 0x0008
@@ -58,93 +111,62 @@
 #define PROP_ERROR_HANDLE_CONTROL_MESSAGE 0x0020
 #define PROP_ERROR_SET_FAILED 0x0024
 
-/*
-** This was previously for testing, but now that SystemProperties is its own testable class,
-** there is never a reason to call this function and its implementation simply returns -1.
-*/
-int __system_property_set_filename(const char* __unused __filename);
-
-/*
-** Initialize the area to be used to store properties.  Can
-** only be done by a single process that has write access to
-** the property area.
-*/
+/**
+ * Initializes the area to be used to store properties.
+ *
+ * Can only be done by the process that has write access to the property area,
+ * typically init.
+ *
+ * See __system_properties_init() for the equivalent for all other processes.
+ */
 int __system_property_area_init(void);
 
-/* Read the global serial number of the system properties
-**
-** Called to predict if a series of cached __system_property_find
-** objects will have seen __system_property_serial values change.
-** But also aids the converse, as changes in the global serial can
-** also be used to predict if a failed __system_property_find
-** could in-turn now find a new object; thus preventing the
-** cycles of effort to poll __system_property_find.
-**
-** Typically called at beginning of a cache cycle to signal if _any_ possible
-** changes have occurred since last. If there is, one may check each individual
-** __system_property_serial to confirm dirty, or __system_property_find
-** to check if the property now exists. If a call to __system_property_add
-** or __system_property_update has completed between two calls to
-** __system_property_area_serial then the second call will return a larger
-** value than the first call. Beware of race conditions as changes to the
-** properties are not atomic, the main value of this call is to determine
-** whether the expensive __system_property_find is worth retrying to see if
-** a property now exists.
-**
-** Returns the serial number on success, -1 on error.
-*/
-uint32_t __system_property_area_serial(void);
-
-/* Add a new system property.  Can only be done by a single
-** process that has write access to the property area, and
-** that process must handle sequencing to ensure the property
-** does not already exist and that only one property is added
-** or updated at a time.
-**
-** Returns 0 on success, -1 if the property area is full.
-*/
+/**
+ * Adds a new system property.
+ * Can only be done by the process that has write access to the property area --
+ * typically init -- which must handle sequencing to ensure that only one property is
+ * updated at a time.
+ *
+ * Returns 0 on success, -1 if the property area is full.
+ */
 int __system_property_add(const char* _Nonnull __name, unsigned int __name_length, const char* _Nonnull __value, unsigned int __value_length);
 
-/* Update the value of a system property returned by
-** __system_property_find.  Can only be done by a single process
-** that has write access to the property area, and that process
-** must handle sequencing to ensure that only one property is
-** updated at a time.
-**
-** Returns 0 on success, -1 if the parameters are incorrect.
-*/
+/**
+ * Updates the value of a system property returned by __system_property_find().
+ * Can only be done by the process that has write access to the property area --
+ * typically init -- which must handle sequencing to ensure that only one property is
+ * updated at a time.
+ *
+ * Returns 0 on success, -1 if the parameters are incorrect.
+ */
 int __system_property_update(prop_info* _Nonnull __pi, const char* _Nonnull __value, unsigned int __value_length);
 
-/* Read the serial number of a system property returned by
-** __system_property_find.
-**
-** Returns the serial number on success, -1 on error.
-*/
-uint32_t __system_property_serial(const prop_info* _Nonnull __pi);
-
-/* Initialize the system properties area in read only mode.
- * Should be done by all processes that need to read system
- * properties.
+/**
+ * Reloads the system properties from disk.
+ * Not intended for use by any apps except the Zygote.
+ * Should only be called from the main thread.
+ *
+ * Pointers received from functions such as __system_property_find()
+ * may be invalidated by calls to this function.
  *
  * Returns 0 on success, -1 otherwise.
- */
-int __system_properties_init(void);
-
-/*
- * Reloads the system properties from disk.
- * Not intended for use by any apps except the Zygote. Should only be called from the main thread.
  *
- * NOTE: Any pointers received from methods such as __system_property_find should be assumed to be
- * invalid after this method is called.
- *
- * Returns 0 on success, -1 if the system properties failed to re-initialize (same conditions as
- * __system properties_init)
+ * Available since API level 35.
  */
-int __system_properties_zygote_reload(void) __INTRODUCED_IN(__ANDROID_API_V__);
+int __system_properties_zygote_reload(void) __INTRODUCED_IN(35);
 
-/* Deprecated: use __system_property_wait instead. */
+//
+// Deprecated functions.
+//
+
+/** Deprecated: use __system_property_wait instead. */
 uint32_t __system_property_wait_any(uint32_t __old_serial);
 
-__END_DECLS
+/**
+ * Deprecated: previously for testing, but now that SystemProperties is its own
+ * testable class, there is never a reason to call this function and its
+ * implementation simply returns -1.
+ */
+int __system_property_set_filename(const char* __unused __filename);
 
-#endif
+__END_DECLS
diff --git a/libc/include/sys/select.h b/libc/include/sys/select.h
index 84c2621..437a234 100644
--- a/libc/include/sys/select.h
+++ b/libc/include/sys/select.h
@@ -44,7 +44,7 @@
 typedef unsigned long fd_mask;
 
 /**
- * The limit on the largest fd that can be used with this API.
+ * The limit on the largest fd that can be used with fd_set.
  * Use <poll.h> instead.
  */
 #define FD_SETSIZE 1024
@@ -52,6 +52,9 @@
 
 /**
  * The type of a file descriptor set. Limited to 1024 fds.
+ * The underlying system calls do not have this limit,
+ * and callers can allocate their own sets with calloc().
+ *
  * Use <poll.h> instead.
  */
 typedef struct {
@@ -60,30 +63,27 @@
 
 #define __FDELT(fd) ((fd) / NFDBITS)
 #define __FDMASK(fd) (1UL << ((fd) % NFDBITS))
-#define __FDS_BITS(type,set) (__BIONIC_CAST(static_cast, type, set)->fds_bits)
-
-/* Inline loop so we don't have to declare memset. */
-#define FD_ZERO(set) \
-  do { \
-    size_t __i; \
-    for (__i = 0; __i < sizeof(fd_set)/sizeof(fd_mask); ++__i) { \
-      (set)->fds_bits[__i] = 0; \
-    } \
-  } while (0)
+#define __FDS_BITS(type, set) (__BIONIC_CAST(static_cast, type, set)->fds_bits)
 
 void __FD_CLR_chk(int, fd_set* _Nonnull , size_t);
 void __FD_SET_chk(int, fd_set* _Nonnull, size_t);
 int __FD_ISSET_chk(int, const fd_set* _Nonnull, size_t);
 
-#define __FD_CLR(fd, set) (__FDS_BITS(fd_set*,set)[__FDELT(fd)] &= ~__FDMASK(fd))
-#define __FD_SET(fd, set) (__FDS_BITS(fd_set*,set)[__FDELT(fd)] |= __FDMASK(fd))
-#define __FD_ISSET(fd, set) ((__FDS_BITS(const fd_set*,set)[__FDELT(fd)] & __FDMASK(fd)) != 0)
+/** FD_CLR() with no bounds checking for users that allocated their own set. */
+#define __FD_CLR(fd, set) (__FDS_BITS(fd_set*, set)[__FDELT(fd)] &= ~__FDMASK(fd))
+/** FD_SET() with no bounds checking for users that allocated their own set. */
+#define __FD_SET(fd, set) (__FDS_BITS(fd_set*, set)[__FDELT(fd)] |= __FDMASK(fd))
+/** FD_ISSET() with no bounds checking for users that allocated their own set. */
+#define __FD_ISSET(fd, set) ((__FDS_BITS(const fd_set*, set)[__FDELT(fd)] & __FDMASK(fd)) != 0)
 
-/** Removes `fd` from the given set. Use <poll.h> instead. */
+/** Removes all 1024 fds from the given set. Use <poll.h> instead. */
+#define FD_ZERO(set) __builtin_memset(set, 0, sizeof(*__BIONIC_CAST(static_cast, const fd_set*, set)))
+
+/** Removes `fd` from the given set. Limited to fds under 1024. Use <poll.h> instead. */
 #define FD_CLR(fd, set) __FD_CLR_chk(fd, set, __bos(set))
-/** Adds `fd` to the given set. Use <poll.h> instead. */
+/** Adds `fd` to the given set. Limited to fds under 1024. Use <poll.h> instead. */
 #define FD_SET(fd, set) __FD_SET_chk(fd, set, __bos(set))
-/** Tests whether `fd` is in the given set. Use <poll.h> instead. */
+/** Tests whether `fd` is in the given set. Limited to fds under 1024. Use <poll.h> instead. */
 #define FD_ISSET(fd, set) __FD_ISSET_chk(fd, set, __bos(set))
 
 /**
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 4298b87..35e67c8 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -844,6 +844,7 @@
     pwrite;
     pwrite64;
     qsort;
+    qsort_r; # introduced=36
     quick_exit;
     raise;
     rand;
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/qsort_r.c b/libc/upstream-freebsd/lib/libc/stdlib/qsort_r.c
new file mode 100644
index 0000000..b382b40
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/qsort_r.c
@@ -0,0 +1,6 @@
+/*
+ * This file is in the public domain.  Originally written by Garrett
+ * A. Wollman.
+ */
+#define I_AM_QSORT_R
+#include "qsort.c"
diff --git a/linker/linker_note_gnu_property_test.cpp b/linker/linker_note_gnu_property_test.cpp
index 41fc47b..960118c 100644
--- a/linker/linker_note_gnu_property_test.cpp
+++ b/linker/linker_note_gnu_property_test.cpp
@@ -137,18 +137,18 @@
     dump_member("entries ", entries);
     if (entries > 0) {
       std::cout << "    raw data:";
-      const uintptr_t offset = note->nhdr.n_descsz + 16;
-      for (uintptr_t offs = 16; offs < offset; ++offs) {
+      const uintptr_t end = note->nhdr.n_descsz + 16;
+      for (uintptr_t offset = 16; offset < end; ++offset) {
         std::cout << std::hex;
-        if ((offs % 8) == 0) {
+        if ((offset % 8) == 0) {
           std::cout << "\n   ";
         }
-        auto value = static_cast<unsigned>(section[offs]);
+        auto value = static_cast<unsigned>(section[offset]);
         std::cout << " ";
         if (value < 0x10) {
           std::cout << "0";
         }
-        std::cout << static_cast<unsigned>(section[offs]);
+        std::cout << static_cast<unsigned>(section[offset]);
       }
       std::cout << std::dec << "\n";
     }
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index ad60efd..b0675c1 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -345,19 +345,19 @@
          ((offset % alignment) == 0);
 }
 
-void* ElfReader::MapData(MappedFileFragment* fragment, off64_t offs, off64_t size) {
+void* ElfReader::MapData(MappedFileFragment* fragment, off64_t offset, off64_t size) {
   off64_t end;
-  CHECK(safe_add(&end, offs, size));
+  CHECK(safe_add(&end, offset, size));
 
   // If the data is already mapped just return it
   if (static_cast<off64_t>(file_fragment_.size()) >= end) {
-    return static_cast<char*>(file_fragment_.data()) + offs;
+    return static_cast<char*>(file_fragment_.data()) + offset;
   }
   // Use the passed-in fragment if area is not mapped. We can't remap the original fragment
   // because that invalidates all previous pointers if the file is remapped to a different
   // virtual address. A local variable can't be used in place of the passed-in fragment because
   // the area would be unmapped as soon as the local object goes out of scope.
-  if (fragment->Map(fd_, file_offset_, offs, size)) {
+  if (fragment->Map(fd_, file_offset_, offset, size)) {
     return fragment->data();
   }
   return nullptr;
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index dc1ca99..e7aae6e 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -73,7 +73,7 @@
   [[nodiscard]] bool FindGnuPropertySection();
   [[nodiscard]] bool CheckPhdr(ElfW(Addr));
   [[nodiscard]] bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
-  [[nodiscard]] void* MapData(MappedFileFragment* fragment, off64_t offs, off64_t size);
+  [[nodiscard]] void* MapData(MappedFileFragment* fragment, off64_t offset, off64_t size);
 
   bool did_read_;
   bool did_load_;
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index a5916d3..813f348 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -1627,6 +1627,7 @@
 #if !defined(__BIONIC__)
   GTEST_SKIP() << "Only valid on bionic";
 #endif
+  SKIP_WITH_HWASAN << "Only test system allocator, not hwasan allocator.";
 
   if (IsLowRamDevice()) {
     GTEST_SKIP() << "Skipped on low memory devices.";
@@ -1657,6 +1658,7 @@
 #if !defined(__BIONIC__)
   GTEST_SKIP() << "Only valid on bionic";
 #endif
+  SKIP_WITH_HWASAN << "Only test system allocator, not hwasan allocator.";
 
   if (IsLowRamDevice()) {
     GTEST_SKIP() << "Skipped on low memory devices.";
@@ -1687,6 +1689,7 @@
 #if !defined(__BIONIC__)
   GTEST_SKIP() << "Only valid on bionic";
 #endif
+  SKIP_WITH_HWASAN << "Only test system allocator, not hwasan allocator.";
 
   if (IsLowRamDevice()) {
     GTEST_SKIP() << "Skipped on low memory devices.";
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index f5e57a5..3216066 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -431,6 +431,31 @@
   ASSERT_STREQ("charlie", entries[2].name);
 }
 
+TEST(stdlib, qsort_r) {
+  struct s {
+    char name[16];
+    static int comparator(const void* lhs, const void* rhs, void* context) {
+      int* count_p = reinterpret_cast<int*>(context);
+      *count_p += 1;
+      return strcmp(reinterpret_cast<const s*>(lhs)->name, reinterpret_cast<const s*>(rhs)->name);
+    }
+  };
+  s entries[3];
+  strcpy(entries[0].name, "charlie");
+  strcpy(entries[1].name, "bravo");
+  strcpy(entries[2].name, "alpha");
+
+  int count;
+  void* context = &count;
+
+  count = 0;
+  qsort_r(entries, 3, sizeof(s), s::comparator, context);
+  ASSERT_STREQ("alpha", entries[0].name);
+  ASSERT_STREQ("bravo", entries[1].name);
+  ASSERT_STREQ("charlie", entries[2].name);
+  ASSERT_EQ(count, 3);
+}
+
 static void* TestBug57421_child(void* arg) {
   pthread_t main_thread = reinterpret_cast<pthread_t>(arg);
   pthread_join(main_thread, nullptr);