Merge "Use an ELF alias for strptime_l()." into main
diff --git a/docs/status.md b/docs/status.md
index 0810499..174c005 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -57,6 +57,7 @@
 
 New libc functions in API level 36:
   * `qsort_r`, `sig2str`/`str2sig` (POSIX Issue 8 additions).
+  * New system call wrapper: `mseal` (`<sys/mman.h>`).
 
 New libc functions in V (API level 35):
   * New `android_crash_detail_register`, `android_crash_detail_unregister`,
diff --git a/libc/Android.bp b/libc/Android.bp
index 245079f..64785a5 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -2257,6 +2257,11 @@
         "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,
 }
 
 ndk_headers {
@@ -2273,6 +2278,7 @@
     to: "scsi",
     srcs: ["kernel/android/scsi/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2281,6 +2287,7 @@
     to: "arm-linux-androideabi",
     srcs: ["kernel/uapi/asm-arm/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2289,6 +2296,7 @@
     to: "aarch64-linux-android",
     srcs: ["kernel/uapi/asm-arm64/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2297,6 +2305,7 @@
     to: "riscv64-linux-android",
     srcs: ["kernel/uapi/asm-riscv/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2305,6 +2314,7 @@
     to: "i686-linux-android",
     srcs: ["kernel/uapi/asm-x86/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_headers {
@@ -2313,6 +2323,7 @@
     to: "x86_64-linux-android",
     srcs: ["kernel/uapi/asm-x86/**/*.h"],
     license: "NOTICE",
+    skip_verification: true,
 }
 
 ndk_library {
diff --git a/libc/bionic/clock.cpp b/libc/bionic/clock.cpp
index 31e6c3c..45d29b7 100644
--- a/libc/bionic/clock.cpp
+++ b/libc/bionic/clock.cpp
@@ -32,7 +32,7 @@
 
 #include "private/bionic_constants.h"
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/clock.html
 clock_t clock() {
   timespec ts;
   clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index ccbbfcf..65749a4 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -117,7 +117,7 @@
   pthread_kill(timer->callback_thread, TIMER_SIGNAL);
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_create.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_create.html
 int timer_create(clockid_t clock_id, sigevent* evp, timer_t* timer_id) {
   PosixTimer* timer = reinterpret_cast<PosixTimer*>(malloc(sizeof(PosixTimer)));
   if (timer == nullptr) {
@@ -201,7 +201,7 @@
   return 0;
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_delete.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_delete.html
 int timer_delete(timer_t id) {
   int rc = __timer_delete(to_kernel_timer_id(id));
   if (rc == -1) {
@@ -220,12 +220,12 @@
   return 0;
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_gettime.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_gettime.html
 int timer_gettime(timer_t id, itimerspec* ts) {
   return __timer_gettime(to_kernel_timer_id(id), ts);
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_settime.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_settime.html
 // When using timer_settime to disarm a repeatable SIGEV_THREAD timer with a very small
 // period (like below 1ms), the kernel may continue to send events to the callback thread
 // for a few extra times. This behavior is fine because in POSIX standard: The effect of
@@ -235,7 +235,7 @@
   return __timer_settime(timer->kernel_timer_id, flags, ts, ots);
 }
 
-// http://pubs.opengroup.org/onlinepubs/9699919799/functions/timer_getoverrun.html
+// https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_getoverrun.html
 int timer_getoverrun(timer_t id) {
   return __timer_getoverrun(to_kernel_timer_id(id));
 }
diff --git a/libc/bionic/sigprocmask.cpp b/libc/bionic/sigprocmask.cpp
index 6d436a6..10e2fa3 100644
--- a/libc/bionic/sigprocmask.cpp
+++ b/libc/bionic/sigprocmask.cpp
@@ -41,18 +41,6 @@
 // can't allow clang to decide to inline sigprocmask.
 //
 
-int sigprocmask(int how,
-                const sigset_t* bionic_new_set,
-                sigset_t* bionic_old_set) __attribute__((__noinline__)) {
-  SigSetConverter new_set{bionic_new_set};
-  SigSetConverter old_set{bionic_old_set};
-  int rc = sigprocmask64(how, new_set.ptr, old_set.ptr);
-  if (rc == 0 && bionic_old_set != nullptr) {
-    old_set.copy_out();
-  }
-  return rc;
-}
-
 int sigprocmask64(int how,
                   const sigset64_t* new_set,
                   sigset64_t* old_set) __attribute__((__noinline__)) {
@@ -70,3 +58,21 @@
   }
   return __rt_sigprocmask(how, mutable_new_set_ptr, old_set, sizeof(*new_set));
 }
+
+#if defined(__LP64__)
+// For LP64, `sigset64_t` and `sigset_t` are the same.
+__strong_alias(sigprocmask, sigprocmask64);
+#else
+// ILP32 needs a shim.
+int sigprocmask(int how,
+                const sigset_t* bionic_new_set,
+                sigset_t* bionic_old_set) __attribute__((__noinline__)) {
+  SigSetConverter new_set{bionic_new_set};
+  SigSetConverter old_set{bionic_old_set};
+  int rc = sigprocmask64(how, new_set.ptr, old_set.ptr);
+  if (rc == 0 && bionic_old_set != nullptr) {
+    old_set.copy_out();
+  }
+  return rc;
+}
+#endif
diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp
index 8cee8b8..d97057f 100644
--- a/libc/bionic/spawn.cpp
+++ b/libc/bionic/spawn.cpp
@@ -187,7 +187,7 @@
                        char* const env[],
                        int exec_fn(const char* path, char* const argv[], char* const env[])) {
   // See https://man7.org/linux/man-pages/man3/posix_spawn.3.html
-  // and http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html
+  // and https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/posix_spawn.html
 
   ScopedSignalBlocker ssb;
 
diff --git a/libc/bionic/strerror.cpp b/libc/bionic/strerror.cpp
index 743130d..c41b547 100644
--- a/libc/bionic/strerror.cpp
+++ b/libc/bionic/strerror.cpp
@@ -102,3 +102,4 @@
   strerror_r(error_number, result, sizeof(tls.strerror_buf));
   return result;
 }
+__strong_alias(strerror_l, strerror);
diff --git a/libc/bionic/string_l.cpp b/libc/bionic/string_l.cpp
index 66bfb0e..84396bf 100644
--- a/libc/bionic/string_l.cpp
+++ b/libc/bionic/string_l.cpp
@@ -33,10 +33,6 @@
   return strcoll(s1, s2);
 }
 
-char* strerror_l(int error, locale_t) {
-  return strerror(error);
-}
-
 size_t strxfrm_l(char* dst, const char* src, size_t n, locale_t) {
   return strxfrm(dst, src, n);
 }
diff --git a/libc/bionic/system.cpp b/libc/bionic/system.cpp
index 93d7497..8349498 100644
--- a/libc/bionic/system.cpp
+++ b/libc/bionic/system.cpp
@@ -38,7 +38,7 @@
 
 int system(const char* command) {
   // "The system() function shall always return non-zero when command is NULL."
-  // http://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html
+  // https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/system.html
   if (command == nullptr) return 1;
 
   ScopedSignalBlocker sigchld_blocker(SIGCHLD);
diff --git a/libc/bionic/wctype.cpp b/libc/bionic/wctype.cpp
index b37f17b..481197a 100644
--- a/libc/bionic/wctype.cpp
+++ b/libc/bionic/wctype.cpp
@@ -55,45 +55,44 @@
 };
 
 int iswalnum(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_ALNUM, isalnum); }
+__strong_alias(iswalnum_l, iswalnum);
 int iswalpha(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_ALPHABETIC, isalpha); }
+__strong_alias(iswalpha_l, iswalpha);
 int iswblank(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_BLANK, isblank); }
+__strong_alias(iswblank_l, iswblank);
 int iswgraph(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_GRAPH, isgraph); }
+__strong_alias(iswgraph_l, iswgraph);
 int iswlower(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_LOWERCASE, islower); }
+__strong_alias(iswlower_l, iswlower);
 int iswprint(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_PRINT, isprint); }
+__strong_alias(iswprint_l, iswprint);
 int iswspace(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_WHITE_SPACE, isspace); }
+__strong_alias(iswspace_l, iswspace);
 int iswupper(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_UPPERCASE, isupper); }
+__strong_alias(iswupper_l, iswupper);
 int iswxdigit(wint_t wc) { return __icu_hasBinaryProperty(wc, UCHAR_POSIX_XDIGIT, isxdigit); }
+__strong_alias(iswxdigit_l, iswxdigit);
 
 int iswcntrl(wint_t wc) {
   typedef int8_t (*FnT)(UChar32);
   static auto u_charType = reinterpret_cast<FnT>(__find_icu_symbol("u_charType"));
   return u_charType ? (u_charType(wc) == U_CONTROL_CHAR) : iscntrl(wc);
 }
+__strong_alias(iswcntrl_l, iswcntrl);
 
 int iswdigit(wint_t wc) {
   typedef UBool (*FnT)(UChar32);
   static auto u_isdigit = reinterpret_cast<FnT>(__find_icu_symbol("u_isdigit"));
   return u_isdigit ? u_isdigit(wc) : isdigit(wc);
 }
+__strong_alias(iswdigit_l, iswdigit);
 
 int iswpunct(wint_t wc) {
   typedef UBool (*FnT)(UChar32);
   static auto u_ispunct = reinterpret_cast<FnT>(__find_icu_symbol("u_ispunct"));
   return u_ispunct ? u_ispunct(wc) : ispunct(wc);
 }
-
-int iswalnum_l(wint_t c, locale_t) { return iswalnum(c); }
-int iswalpha_l(wint_t c, locale_t) { return iswalpha(c); }
-int iswblank_l(wint_t c, locale_t) { return iswblank(c); }
-int iswcntrl_l(wint_t c, locale_t) { return iswcntrl(c); }
-int iswdigit_l(wint_t c, locale_t) { return iswdigit(c); }
-int iswgraph_l(wint_t c, locale_t) { return iswgraph(c); }
-int iswlower_l(wint_t c, locale_t) { return iswlower(c); }
-int iswprint_l(wint_t c, locale_t) { return iswprint(c); }
-int iswpunct_l(wint_t c, locale_t) { return iswpunct(c); }
-int iswspace_l(wint_t c, locale_t) { return iswspace(c); }
-int iswupper_l(wint_t c, locale_t) { return iswupper(c); }
-int iswxdigit_l(wint_t c, locale_t) { return iswxdigit(c); }
+__strong_alias(iswpunct_l, iswpunct);
 
 int iswctype(wint_t wc, wctype_t char_class) {
   if (char_class < WC_TYPE_ALNUM || char_class > WC_TYPE_XDIGIT) return 0;
@@ -103,10 +102,7 @@
   };
   return fns[char_class - WC_TYPE_ALNUM](wc);
 }
-
-int iswctype_l(wint_t wc, wctype_t char_class, locale_t) {
-  return iswctype(wc, char_class);
-}
+__strong_alias(iswctype_l, iswctype);
 
 wint_t towlower(wint_t wc) {
   if (wc < 0x80) return tolower(wc);
@@ -115,6 +111,7 @@
   static auto u_tolower = reinterpret_cast<FnT>(__find_icu_symbol("u_tolower"));
   return u_tolower ? u_tolower(wc) : tolower(wc);
 }
+__strong_alias(towlower_l, towlower);
 
 wint_t towupper(wint_t wc) {
   if (wc < 0x80) return toupper(wc);
@@ -123,9 +120,7 @@
   static auto u_toupper = reinterpret_cast<FnT>(__find_icu_symbol("u_toupper"));
   return u_toupper ? u_toupper(wc) : toupper(wc);
 }
-
-wint_t towupper_l(wint_t c, locale_t) { return towupper(c); }
-wint_t towlower_l(wint_t c, locale_t) { return towlower(c); }
+__strong_alias(towupper_l, towupper);
 
 wctype_t wctype(const char* property) {
   static const char* const  properties[WC_TYPE_MAX - 1] = {
@@ -139,10 +134,7 @@
   }
   return static_cast<wctype_t>(0);
 }
-
-wctype_t wctype_l(const char* property, locale_t) {
-  return wctype(property);
-}
+__strong_alias(wctype_l, wctype);
 
 static wctrans_t wctrans_tolower = wctrans_t(1);
 static wctrans_t wctrans_toupper = wctrans_t(2);
@@ -153,10 +145,7 @@
   errno = EINVAL;
   return nullptr;
 }
-
-wctrans_t wctrans_l(const char* name, locale_t) {
-  return wctrans(name);
-}
+__strong_alias(wctrans_l, wctrans);
 
 wint_t towctrans(wint_t c, wctrans_t t) {
   if (t == wctrans_tolower) return towlower(c);
@@ -164,7 +153,4 @@
   errno = EINVAL;
   return c;
 }
-
-wint_t towctrans_l(wint_t c, wctrans_t t, locale_t) {
-  return towctrans(c, t);
-}
+__strong_alias(towctrans_l, towctrans);
diff --git a/libc/stdio/fmemopen.cpp b/libc/stdio/fmemopen.cpp
index c58fca9..f069da4 100644
--- a/libc/stdio/fmemopen.cpp
+++ b/libc/stdio/fmemopen.cpp
@@ -33,7 +33,7 @@
 
 #include "local.h"
 
-// See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html
+// See https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/fmemopen.html
 // and https://man7.org/linux/man-pages/man3/fmemopen.3.html for documentation.
 
 struct fmemopen_cookie {
diff --git a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
index ff6b26e..3ec0222 100644
--- a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
+++ b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
@@ -46,11 +46,11 @@
  *
  * Derived from The Open Group Base Specifications Issue 7, IEEE Std 1003.1-2008
  * as described in;
- *   http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html
+ *   https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/fnmatch.html
  *
  * Filename pattern matches defined in section 2.13, "Pattern Matching Notation"
  * from chapter 2. "Shell Command Language"
- *   http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13
+ *   https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/utilities/V3_chap02.html#tag_18_13
  * where; 1. A bracket expression starting with an unquoted <circumflex> '^'
  * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.'
  * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading
@@ -61,7 +61,7 @@
  *
  * Bracket expansion defined in section 9.3.5, "RE Bracket Expression",
  * from chapter 9, "Regular Expressions"
- *   http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
+ *   https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/basedefs/V1_chap09.html#tag_09_03_05
  * with no support for collating symbols, equivalence class expressions or
  * character class expressions.  A partial range expression with a leading
  * hyphen following a valid range expression will match only the ordinary
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 3216066..fac9b9b 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -519,7 +519,7 @@
 
 TEST(stdlib, system_NULL) {
   // "The system() function shall always return non-zero when command is NULL."
-  // http://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html
+  // https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/system.html
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wnonnull"
   ASSERT_NE(0, system(nullptr));
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 387d23b..a811fd8 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -556,7 +556,7 @@
   } else {
     // If the subject sequence begins with a <hyphen-minus>, the value resulting
     // from the conversion shall be negated.
-    // http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoul.html
+    // https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/strtoul.html
     ASSERT_EQ(std::numeric_limits<T>::max(), fn(min_str, nullptr, 0)) << min_str;
   }
   ASSERT_EQ(std::numeric_limits<T>::max(), fn(max_str, nullptr, 0)) << max_str;