Merge "Add POSIX 2024 NSIG_MAX." into main
diff --git a/libc/arch-x86/string/sse2-memmove-slm.S b/libc/arch-x86/string/sse2-memmove-slm.S
index 2ed4e7b..a25b4c7 100644
--- a/libc/arch-x86/string/sse2-memmove-slm.S
+++ b/libc/arch-x86/string/sse2-memmove-slm.S
@@ -96,6 +96,13 @@
 #define SETUP_PIC_REG(x)	call	__x86.get_pc_thunk.x
 
 	.section .text.sse2,"ax",@progbits
+ENTRY (__memcpy_chk)
+/* NOTE: We can't use LEN here because ebx has not been pushed yet. */
+	movl	12(%esp), %ecx
+	cmpl	16(%esp), %ecx
+	ja	__memcpy_chk_fail
+/* Fall through to memcpy/memmove. */
+END (__memcpy_chk)
 ENTRY (MEMMOVE)
 	ENTRANCE
 	movl	LEN(%esp), %ecx
diff --git a/libc/arch-x86_64/string/sse2-memmove-slm.S b/libc/arch-x86_64/string/sse2-memmove-slm.S
index b787385..9f5fb12 100644
--- a/libc/arch-x86_64/string/sse2-memmove-slm.S
+++ b/libc/arch-x86_64/string/sse2-memmove-slm.S
@@ -99,6 +99,11 @@
 #define RETURN		RETURN_END;
 
 	.section .text.sse2,"ax",@progbits
+ENTRY (__memcpy_chk)
+	cmp	%rcx, %rdx
+	ja	__memcpy_chk_fail
+/* Fall through to memcpy/memmove. */
+END (__memcpy_chk)
 ENTRY (MEMMOVE)
 	ENTRANCE
 	mov	%rdi, %rax
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index 80f7c20..15053d3 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -489,16 +489,6 @@
   return strcpy(dst, src);
 }
 
-#if !defined(__arm__) && !defined(__aarch64__) && !defined(__riscv)
-// Runtime implementation of __memcpy_chk (used directly by compiler, not in headers).
-// arm32,arm64,riscv have assembler implementations, and don't need this C fallback.
-extern "C" void* __memcpy_chk(void* dst, const void* src, size_t count, size_t dst_len) {
-  __check_count("memcpy", "count", count);
-  __check_buffer_access("memcpy", "write into", count, dst_len);
-  return memcpy(dst, src, count);
-}
-#endif
-
 // Runtime implementation of __mempcpy_chk (used directly by compiler, not in headers).
 extern "C" void* __mempcpy_chk(void* dst, const void* src, size_t count, size_t dst_len) {
   __check_count("mempcpy", "count", count);
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index 571370c..03822ed 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -210,6 +210,7 @@
       // are vestigial anyway, so the "maximum maximum" of NGROUPS_MAX is a good
       // enough answer for _SC_NGROUPS_MAX...
       return NGROUPS_MAX;
+    case _SC_NSIG:              return NSIG;
     case _SC_PASS_MAX:          return PASS_MAX;
     case _SC_2_C_BIND:          return _POSIX2_C_BIND;
     case _SC_2_C_DEV:           return _POSIX2_C_DEV;
diff --git a/libc/include/bits/sysconf.h b/libc/include/bits/sysconf.h
index ecf26ba..303f7c6 100644
--- a/libc/include/bits/sysconf.h
+++ b/libc/include/bits/sysconf.h
@@ -328,6 +328,8 @@
 #define _SC_LEVEL4_CACHE_ASSOC 0x009c
 /** sysconf() query for the L4 cache line size. Not available on all architectures. */
 #define _SC_LEVEL4_CACHE_LINESIZE 0x009d
+/** sysconf() query equivalent to NSIG. Available from API level 37. */
+#define _SC_NSIG 0x009e
 
 __BEGIN_DECLS
 
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 7b64fbf..ee71f03 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -53,7 +53,7 @@
 
 TEST_F(DEATHTEST, stpncpy_fortified2) {
   foo myfoo;
-  int copy_amt = atoi("11");
+  volatile int copy_amt = 11;
   ASSERT_FORTIFY(stpncpy(myfoo.a, "01234567890", copy_amt));
 }
 
@@ -65,7 +65,7 @@
 
 TEST_F(DEATHTEST, strncpy_fortified2) {
   foo myfoo;
-  int copy_amt = atoi("11");
+  volatile int copy_amt = 11;
   ASSERT_FORTIFY(strncpy(myfoo.a, "01234567890", copy_amt));
 }
 
@@ -87,13 +87,11 @@
   ASSERT_FORTIFY(sprintf(myfoo.a, "0123456789"));
 }
 
-static int vsprintf_helper2(const char *fmt, ...) {
-  foo myfoo;
+static int vsprintf_helper2(const char* fmt, ...) {
   va_list va;
-  int result;
-
   va_start(va, fmt);
-  result = vsprintf(myfoo.a, fmt, va); // should crash here
+  foo myfoo;
+  int result = vsprintf(myfoo.a, fmt, va); // should crash here
   va_end(va);
   return result;
 }
@@ -106,14 +104,12 @@
   ASSERT_FORTIFY(vsprintf_helper2("0123456789"));
 }
 
-static int vsnprintf_helper2(const char *fmt, ...) {
-  foo myfoo;
+static int vsnprintf_helper2(const char* fmt, ...) {
   va_list va;
-  int result;
-  size_t size = atoi("11");
-
   va_start(va, fmt);
-  result = vsnprintf(myfoo.a, size, fmt, va); // should crash here
+  foo myfoo;
+  volatile size_t size = 11;
+  int result = vsnprintf(myfoo.a, size, fmt, va); // should crash here
   va_end(va);
   return result;
 }
@@ -249,7 +245,7 @@
 
 TEST_F(DEATHTEST, strncat_fortified2) {
   foo myfoo;
-  size_t n = atoi("10"); // avoid compiler optimizations
+  volatile size_t n = 10;
   strncpy(myfoo.a, "012345678", n);
   ASSERT_FORTIFY(strncat(myfoo.a, "9", n));
 }
@@ -257,7 +253,7 @@
 TEST_F(DEATHTEST, strncat2_fortified2) {
   foo myfoo;
   myfoo.a[0] = '\0';
-  size_t n = atoi("10"); // avoid compiler optimizations
+  volatile size_t n = 10;
   ASSERT_FORTIFY(strncat(myfoo.a, "0123456789", n));
 }
 
@@ -265,7 +261,7 @@
   foo myfoo;
   memcpy(myfoo.a, "0123456789", sizeof(myfoo.a)); // unterminated string
   myfoo.b[0] = '\0';
-  size_t n = atoi("10"); // avoid compiler optimizations
+  volatile size_t n = 10;
   ASSERT_FORTIFY(strncat(myfoo.b, myfoo.a, n));
 }
 
@@ -294,7 +290,7 @@
 TEST_F(DEATHTEST, bzero_fortified2) {
   foo myfoo;
   memcpy(myfoo.b, "0123456789", sizeof(myfoo.b));
-  size_t n = atoi("11");
+  volatile size_t n = 11;
   ASSERT_FORTIFY(bzero(myfoo.b, n));
 }
 
@@ -304,7 +300,7 @@
 TEST_F(DEATHTEST, strcpy_fortified) {
 #if defined(__BIONIC__)
   char buf[10];
-  char *orig = strdup("0123456789");
+  char* orig = strdup("0123456789");
   ASSERT_FORTIFY(strcpy(buf, orig));
   free(orig);
 #else // __BIONIC__
@@ -316,7 +312,7 @@
 TEST_F(DEATHTEST, strcpy2_fortified) {
 #if defined(__BIONIC__)
   char buf[0];
-  char *orig = strdup("");
+  char* orig = strdup("");
   ASSERT_FORTIFY(strcpy(buf, orig));
   free(orig);
 #else // __BIONIC__
@@ -328,7 +324,7 @@
 TEST_F(DEATHTEST, strcpy3_fortified) {
 #if defined(__BIONIC__)
   char buf[0];
-  char *orig = strdup("1");
+  char* orig = strdup("1");
   ASSERT_FORTIFY(strcpy(buf, orig));
   free(orig);
 #else // __BIONIC__
@@ -340,7 +336,7 @@
 TEST_F(DEATHTEST, strcpy4_fortified) {
 #if defined(__BIONIC__)
   char buf[1];
-  char *orig = strdup("12");
+  char* orig = strdup("12");
   ASSERT_FORTIFY(strcpy(buf, orig));
   free(orig);
 #else // __BIONIC__
@@ -411,7 +407,7 @@
 }
 
 TEST_F(DEATHTEST, sprintf_malloc_fortified) {
-  char* buf = (char *) malloc(10);
+  char* buf = static_cast<char*>(malloc(10));
   char source_buf[11];
   memcpy(source_buf, "1234567890", 11);
   ASSERT_FORTIFY(sprintf(buf, "%s", source_buf));
@@ -423,13 +419,11 @@
   ASSERT_FORTIFY(sprintf(buf, "aaaaa"));
 }
 
-static int vsprintf_helper(const char *fmt, ...) {
-  char buf[10];
+static int vsprintf_helper(const char* fmt, ...) {
   va_list va;
-  int result;
-
   va_start(va, fmt);
-  result = vsprintf(buf, fmt, va); // should crash here
+  char buf[10];
+  int result = vsprintf(buf, fmt, va); // should crash here
   va_end(va);
   return result;
 }
@@ -442,14 +436,12 @@
   ASSERT_FORTIFY(vsprintf_helper("0123456789"));
 }
 
-static int vsnprintf_helper(const char *fmt, ...) {
-  char buf[10];
+static int vsnprintf_helper(const char* fmt, ...) {
   va_list va;
-  int result;
-  size_t size = atoi("11");
-
   va_start(va, fmt);
-  result = vsnprintf(buf, size, fmt, va); // should crash here
+  char buf[10];
+  volatile size_t size = 11;
+  int result = vsnprintf(buf, size, fmt, va); // should crash here
   va_end(va);
   return result;
 }
@@ -464,7 +456,7 @@
 
 TEST_F(DEATHTEST, strncat_fortified) {
   char buf[10];
-  size_t n = atoi("10"); // avoid compiler optimizations
+  volatile size_t n = 10;
   strncpy(buf, "012345678", n);
   ASSERT_FORTIFY(strncat(buf, "9", n));
 }
@@ -472,7 +464,7 @@
 TEST_F(DEATHTEST, strncat2_fortified) {
   char buf[10];
   buf[0] = '\0';
-  size_t n = atoi("10"); // avoid compiler optimizations
+  volatile size_t n = 10;
   ASSERT_FORTIFY(strncat(buf, "0123456789", n));
 }
 
@@ -487,7 +479,7 @@
 TEST_F(DEATHTEST, memmove_fortified) {
   char buf[20];
   strcpy(buf, "0123456789");
-  size_t n = atoi("10");
+  volatile size_t n = 10;
   ASSERT_FORTIFY(memmove(buf + 11, buf, n));
 }
 
@@ -495,13 +487,13 @@
   char bufa[10];
   char bufb[10];
   strcpy(bufa, "012345678");
-  size_t n = atoi("11");
+  volatile size_t n = 11;
   ASSERT_FORTIFY(memcpy(bufb, bufa, n));
 }
 
 TEST_F(DEATHTEST, memset_fortified) {
   char buf[10];
-  size_t n = atoi("11");
+  volatile size_t n = 11;
   ASSERT_FORTIFY(memset(buf, 0, n));
 }
 
@@ -547,23 +539,23 @@
 TEST_F(DEATHTEST, bzero_fortified) {
   char buf[10];
   memcpy(buf, "0123456789", sizeof(buf));
-  size_t n = atoi("11");
+  size_t n = 11;
   ASSERT_FORTIFY(bzero(buf, n));
 }
 
 TEST_F(DEATHTEST, umask_fortified) {
-  mode_t mask = atoi("1023");  // 01777 in octal
+  volatile mode_t mask = 01777;
   ASSERT_FORTIFY(umask(mask));
 }
 
 TEST_F(DEATHTEST, recv_fortified) {
-  size_t data_len = atoi("11"); // suppress compiler optimizations
+  volatile size_t data_len = 11;
   char buf[10];
   ASSERT_FORTIFY(recv(0, buf, data_len, 0));
 }
 
 TEST_F(DEATHTEST, send_fortified) {
-  size_t data_len = atoi("11"); // suppress compiler optimizations
+  volatile size_t data_len = 11;
   char buf[10] = {0};
   ASSERT_FORTIFY(send(0, buf, data_len, 0));
 }
@@ -583,84 +575,84 @@
 
 TEST_F(DEATHTEST, getcwd_fortified) {
   char buf[1];
-  size_t ct = atoi("2"); // prevent optimizations
-  ASSERT_FORTIFY(getcwd(buf, ct));
+  volatile size_t n = 2;
+  ASSERT_FORTIFY(getcwd(buf, n));
 }
 
 TEST_F(DEATHTEST, pread_fortified) {
   char buf[1];
-  size_t ct = atoi("2"); // prevent optimizations
+  volatile size_t n = 2;
   int fd = open("/dev/null", O_RDONLY);
-  ASSERT_FORTIFY(pread(fd, buf, ct, 0));
+  ASSERT_FORTIFY(pread(fd, buf, n, 0));
   close(fd);
 }
 
 TEST_F(DEATHTEST, pread64_fortified) {
   char buf[1];
-  size_t ct = atoi("2"); // prevent optimizations
+  volatile size_t n = 2;
   int fd = open("/dev/null", O_RDONLY);
-  ASSERT_FORTIFY(pread64(fd, buf, ct, 0));
+  ASSERT_FORTIFY(pread64(fd, buf, n, 0));
   close(fd);
 }
 
 TEST_F(DEATHTEST, pwrite_fortified) {
   char buf[1] = {0};
-  size_t ct = atoi("2"); // prevent optimizations
+  volatile size_t n = 2;
   int fd = open("/dev/null", O_WRONLY);
-  ASSERT_FORTIFY(pwrite(fd, buf, ct, 0));
+  ASSERT_FORTIFY(pwrite(fd, buf, n, 0));
   close(fd);
 }
 
 TEST_F(DEATHTEST, pwrite64_fortified) {
   char buf[1] = {0};
-  size_t ct = atoi("2"); // prevent optimizations
+  volatile size_t n = 2;
   int fd = open("/dev/null", O_WRONLY);
-  ASSERT_FORTIFY(pwrite64(fd, buf, ct, 0));
+  ASSERT_FORTIFY(pwrite64(fd, buf, n, 0));
   close(fd);
 }
 
 TEST_F(DEATHTEST, read_fortified) {
   char buf[1];
-  size_t ct = atoi("2"); // prevent optimizations
+  volatile size_t n = 2;
   int fd = open("/dev/null", O_RDONLY);
-  ASSERT_FORTIFY(read(fd, buf, ct));
+  ASSERT_FORTIFY(read(fd, buf, n));
   close(fd);
 }
 
 TEST_F(DEATHTEST, write_fortified) {
   char buf[1] = {0};
-  size_t ct = atoi("2"); // prevent optimizations
+  volatile size_t n = 2;
   int fd = open("/dev/null", O_WRONLY);
-  ASSERT_EXIT(write(fd, buf, ct), testing::KilledBySignal(SIGABRT), "");
+  ASSERT_FORTIFY(write(fd, buf, n));
   close(fd);
 }
 
 TEST_F(DEATHTEST, fread_fortified) {
   char buf[1];
-  size_t ct = atoi("2"); // prevent optimizations
+  volatile size_t n = 2;
   FILE* fp = fopen("/dev/null", "r");
-  ASSERT_FORTIFY(fread(buf, 1, ct, fp));
+  ASSERT_FORTIFY(fread(buf, 1, n, fp));
   fclose(fp);
 }
 
 TEST_F(DEATHTEST, fwrite_fortified) {
   char buf[1] = {0};
-  size_t ct = atoi("2"); // prevent optimizations
+  volatile size_t n = 2;
   FILE* fp = fopen("/dev/null", "w");
-  ASSERT_FORTIFY(fwrite(buf, 1, ct, fp));
+  ASSERT_FORTIFY(fwrite(buf, 1, n, fp));
   fclose(fp);
 }
 
 TEST_F(DEATHTEST, readlink_fortified) {
   char buf[1];
-  size_t ct = atoi("2"); // prevent optimizations
-  ASSERT_FORTIFY(readlink("/dev/null", buf, ct));
+  volatile size_t n = 2;
+  ASSERT_FORTIFY(readlink("/dev/null", buf, n));
 }
 
 TEST_F(DEATHTEST, readlinkat_fortified) {
   char buf[1];
-  size_t ct = atoi("2"); // prevent optimizations
-  ASSERT_FORTIFY(readlinkat(AT_FDCWD, "/dev/null", buf, ct));
+  volatile size_t n = 2;
+  ASSERT_FORTIFY(readlinkat(AT_FDCWD, "/dev/null", buf, n));
 }
 
 TEST(TEST_NAME, snprintf_nullptr_valid) {
@@ -904,7 +896,8 @@
   memset(buf, 'A', sizeof(buf));
   buf[0] = 'a';
   buf[1] = '\0';
-  char* res = __strcat_chk(buf, "01234567", (size_t)-1);
+  volatile size_t n = -1;
+  char* res = __strcat_chk(buf, "01234567", n);
   ASSERT_EQ(buf, res);
   ASSERT_EQ('a',  buf[0]);
   ASSERT_EQ('0',  buf[1]);
@@ -940,7 +933,8 @@
 
 TEST(TEST_NAME, stpcpy_chk_max_int_size) {
   char buf[10];
-  char* res = __stpcpy_chk(buf, "012345678", (size_t)-1);
+  volatile size_t n = -1;
+  char* res = __stpcpy_chk(buf, "012345678", n);
   ASSERT_EQ(buf + strlen("012345678"), res);
   ASSERT_STREQ("012345678", buf);
 }
@@ -949,16 +943,52 @@
 
 TEST(TEST_NAME, strcpy_chk_max_int_size) {
   char buf[10];
-  char* res = __strcpy_chk(buf, "012345678", (size_t)-1);
+  volatile size_t n = -1;
+  char* res = __strcpy_chk(buf, "012345678", n);
   ASSERT_EQ(buf, res);
   ASSERT_STREQ("012345678", buf);
 }
 
 extern "C" void* __memcpy_chk(void*, const void*, size_t, size_t);
 
+TEST(TEST_NAME, memcpy_chk_smaller) {
+  char buf[10] = "XXXXXXXXX";
+  volatile size_t n = 5;
+  void* res = __memcpy_chk(buf, "012346578", n, sizeof(buf));
+  ASSERT_EQ((void*)buf, res);
+  ASSERT_EQ('0',  buf[0]);
+  ASSERT_EQ('1',  buf[1]);
+  ASSERT_EQ('2',  buf[2]);
+  ASSERT_EQ('3',  buf[3]);
+  ASSERT_EQ('4',  buf[4]);
+  ASSERT_EQ('X',  buf[5]);
+  ASSERT_EQ('X',  buf[6]);
+  ASSERT_EQ('X',  buf[7]);
+  ASSERT_EQ('X',  buf[8]);
+  ASSERT_EQ('\0', buf[9]);
+}
+
+TEST(TEST_NAME, memcpy_chk_exact_size) {
+  char buf[10] = "XXXXXXXXX";
+  volatile size_t n = 10;
+  void* res = __memcpy_chk(buf, "012345678", n, sizeof(buf));
+  ASSERT_EQ((void*)buf, res);
+  ASSERT_EQ('0',  buf[0]);
+  ASSERT_EQ('1',  buf[1]);
+  ASSERT_EQ('2',  buf[2]);
+  ASSERT_EQ('3',  buf[3]);
+  ASSERT_EQ('4',  buf[4]);
+  ASSERT_EQ('5',  buf[5]);
+  ASSERT_EQ('6',  buf[6]);
+  ASSERT_EQ('7',  buf[7]);
+  ASSERT_EQ('8',  buf[8]);
+  ASSERT_EQ('\0', buf[9]);
+}
+
 TEST(TEST_NAME, memcpy_chk_max_int_size) {
   char buf[10];
-  void* res = __memcpy_chk(buf, "012345678", sizeof(buf), (size_t)-1);
+  volatile size_t n = -1;
+  void* res = __memcpy_chk(buf, "012345678", sizeof(buf), n);
   ASSERT_EQ((void*)buf, res);
   ASSERT_EQ('0',  buf[0]);
   ASSERT_EQ('1',  buf[1]);
@@ -991,38 +1021,36 @@
 }
 
 TEST_F(DEATHTEST, poll_fortified) {
-  nfds_t fd_count = atoi("2"); // suppress compiler optimizations
+  volatile nfds_t fd_count = 2;
   pollfd buf[1] = {{0, POLLIN, 0}};
   // Set timeout to zero to prevent waiting in poll when fortify test fails.
   ASSERT_FORTIFY(poll(buf, fd_count, 0));
 }
 
 TEST_F(DEATHTEST, ppoll_fortified) {
-  nfds_t fd_count = atoi("2"); // suppress compiler optimizations
+  volatile nfds_t fd_count = 2;
   pollfd buf[1] = {{0, POLLIN, 0}};
-  // Set timeout to zero to prevent waiting in ppoll when fortify test fails.
-  timespec timeout;
-  timeout.tv_sec = timeout.tv_nsec = 0;
+  // Set timeout to zero to prevent waiting in ppoll if fortify test fails.
+  timespec timeout = {};
   ASSERT_FORTIFY(ppoll(buf, fd_count, &timeout, nullptr));
 }
 
 TEST_F(DEATHTEST, ppoll64_fortified) {
 #if defined(__BIONIC__)        // glibc doesn't have ppoll64.
-  nfds_t fd_count = atoi("2"); // suppress compiler optimizations
+  volatile nfds_t fd_count = 2;
   pollfd buf[1] = {{0, POLLIN, 0}};
-  // Set timeout to zero to prevent waiting in ppoll when fortify test fails.
-  timespec timeout;
-  timeout.tv_sec = timeout.tv_nsec = 0;
+  // Set timeout to zero to prevent waiting in ppoll if fortify test fails.
+  timespec timeout= {};
   ASSERT_FORTIFY(ppoll64(buf, fd_count, &timeout, nullptr));
 #endif
 }
 
 TEST_F(DEATHTEST, open_O_CREAT_without_mode_fortified) {
-  int flags = O_CREAT; // Fool the compiler.
+  volatile int flags = O_CREAT;
   ASSERT_FORTIFY(open("", flags));
 }
 
 TEST_F(DEATHTEST, open_O_TMPFILE_without_mode_fortified) {
-  int flags = O_TMPFILE; // Fool the compiler.
+  volatile int flags = O_TMPFILE;
   ASSERT_FORTIFY(open("", flags));
 }
diff --git a/tests/headers/posix/dlfcn_h.c b/tests/headers/posix/dlfcn_h.c
index 4800075..e8dc648 100644
--- a/tests/headers/posix/dlfcn_h.c
+++ b/tests/headers/posix/dlfcn_h.c
@@ -36,6 +36,17 @@
   MACRO(RTLD_GLOBAL);
   MACRO(RTLD_LOCAL);
 
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  TYPE(Dl_info);
+  STRUCT_MEMBER(Dl_info, const char*, dli_fname);
+  STRUCT_MEMBER(Dl_info, void*, dli_fbase);
+  STRUCT_MEMBER(Dl_info, const char*, dli_sname);
+  STRUCT_MEMBER(Dl_info, void*, dli_saddr);
+#endif
+
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  FUNCTION(dladdr, int (*f)(const void*, Dl_info*));
+#endif
   FUNCTION(dlclose, int (*f)(void*));
   FUNCTION(dlerror, char* (*f)(void));
   FUNCTION(dlopen, void* (*f)(const char*, int));
diff --git a/tests/headers/posix/poll_h.c b/tests/headers/posix/poll_h.c
index 4fce5e5..505ba46 100644
--- a/tests/headers/posix/poll_h.c
+++ b/tests/headers/posix/poll_h.c
@@ -36,6 +36,11 @@
   STRUCT_MEMBER(struct pollfd, short, events);
   STRUCT_MEMBER(struct pollfd, short, revents);
 
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  TYPE(sigset_t);
+  TYPE(struct timespec);
+#endif
+
   TYPE(nfds_t);
 
   MACRO(POLLIN);
@@ -50,4 +55,7 @@
   MACRO(POLLNVAL);
 
   FUNCTION(poll, int (*f)(struct pollfd[], nfds_t, int));
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  FUNCTION(ppoll, int (*f)(struct pollfd[], nfds_t, const struct timespec*, const sigset_t*));
+#endif
 }
diff --git a/tests/headers/posix/pthread_h.c b/tests/headers/posix/pthread_h.c
index 4be822c..3713aff 100644
--- a/tests/headers/posix/pthread_h.c
+++ b/tests/headers/posix/pthread_h.c
@@ -116,6 +116,9 @@
   FUNCTION(pthread_cancel, int (*f)(pthread_t));
 #endif
   FUNCTION(pthread_cond_broadcast, int (*f)(pthread_cond_t*));
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  FUNCTION(pthread_cond_clockwait, int (*f)(pthread_cond_t*, pthread_mutex_t*, clockid_t, const struct timespec*));
+#endif
   FUNCTION(pthread_cond_destroy, int (*f)(pthread_cond_t*));
   FUNCTION(pthread_cond_init, int (*f)(pthread_cond_t*, const pthread_condattr_t*));
   FUNCTION(pthread_cond_signal, int (*f)(pthread_cond_t*));
@@ -140,6 +143,9 @@
   FUNCTION(pthread_join, int (*f)(pthread_t, void**));
   FUNCTION(pthread_key_create, int (*f)(pthread_key_t*, void (*)(void*)));
   FUNCTION(pthread_key_delete, int (*f)(pthread_key_t));
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  FUNCTION(pthread_mutex_clocklock, int (*f)(pthread_mutex_t*, clockid_t, const struct timespec*));
+#endif
 #if !defined(__BIONIC__) // No robust mutexes on Android.
   FUNCTION(pthread_mutex_consistent, int (*f)(pthread_mutex_t*));
 #endif
@@ -176,6 +182,10 @@
 #endif
   FUNCTION(pthread_mutexattr_settype, int (*f)(pthread_mutexattr_t*, int));
   FUNCTION(pthread_once, int (*f)(pthread_once_t*, void (*)(void)));
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  FUNCTION(pthread_rwlock_clockrdlock, int (*f)(pthread_rwlock_t*, clockid_t, const struct timespec*));
+  FUNCTION(pthread_rwlock_clockwrlock, int (*f)(pthread_rwlock_t*, clockid_t, const struct timespec*));
+#endif
   FUNCTION(pthread_rwlock_destroy, int (*f)(pthread_rwlock_t*));
   FUNCTION(pthread_rwlock_init, int (*f)(pthread_rwlock_t*, const pthread_rwlockattr_t*));
   FUNCTION(pthread_rwlock_rdlock, int (*f)(pthread_rwlock_t*));
diff --git a/tests/headers/posix/semaphore_h.c b/tests/headers/posix/semaphore_h.c
index 9d5c7e1..d813363 100644
--- a/tests/headers/posix/semaphore_h.c
+++ b/tests/headers/posix/semaphore_h.c
@@ -35,6 +35,9 @@
 
   MACRO(SEM_FAILED);
 
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  FUNCTION(sem_clockwait, int (*f)(sem_t*, clockid_t, const struct timespec*));
+#endif
   FUNCTION(sem_close, int (*f)(sem_t*));
   FUNCTION(sem_destroy, int (*f)(sem_t*));
   FUNCTION(sem_getvalue, int (*f)(sem_t*, int*));
diff --git a/tests/headers/posix/signal_h.c b/tests/headers/posix/signal_h.c
index 82751f4..3b50fb9 100644
--- a/tests/headers/posix/signal_h.c
+++ b/tests/headers/posix/signal_h.c
@@ -75,6 +75,10 @@
   i = SIGRTMIN;
   i = SIGRTMAX;
 
+#if !defined(__GLIBC__)  // Our glibc is too old.
+  MACRO(SIG2STR_MAX);
+#endif
+
   MACRO(SIGABRT);
   MACRO(SIGALRM);
   MACRO(SIGBUS);
diff --git a/tests/headers/posix/stdlib_h.c b/tests/headers/posix/stdlib_h.c
index 95769b4..deedc06 100644
--- a/tests/headers/posix/stdlib_h.c
+++ b/tests/headers/posix/stdlib_h.c
@@ -119,6 +119,9 @@
   FUNCTION(rand_r, int (*f)(unsigned*));
   FUNCTION(random, long (*f)(void));
   FUNCTION(realloc, void* (*f)(void*, size_t));
+#if !defined(__GLIBC__) // Our glibc is too old.
+  FUNCTION(reallocarray, void* (*f)(void*, size_t, size_t));
+#endif
   FUNCTION(realpath, char* (*f)(const char*, char*));
   FUNCTION(seed48, unsigned short* (*f)(unsigned short[3]));
   FUNCTION(setenv, int (*f)(const char*, const char*, int));
diff --git a/tests/headers/posix/string_h.c b/tests/headers/posix/string_h.c
index 2440050..59a541f 100644
--- a/tests/headers/posix/string_h.c
+++ b/tests/headers/posix/string_h.c
@@ -39,6 +39,9 @@
   FUNCTION(memchr, void* (*f)(const void*, int, size_t));
   FUNCTION(memcmp, int (*f)(const void*, const void*, size_t));
   FUNCTION(memcpy, void* (*f)(void*, const void*, size_t));
+#if !defined(__GLIBC__) // Our glibc is too old.
+  FUNCTION(memmem, void* (*f)(const void*, size_t, const void*, size_t));
+#endif
   FUNCTION(memmove, void* (*f)(void*, const void*, size_t));
   FUNCTION(memset, void* (*f)(void*, int, size_t));
   FUNCTION(stpcpy, char* (*f)(char*, const char*));
@@ -54,6 +57,10 @@
   FUNCTION(strerror, char* (*f)(int));
   FUNCTION(strerror_l, char* (*f)(int, locale_t));
   FUNCTION(strerror_r, int (*f)(int, char*, size_t));
+#if !defined(__GLIBC__) // Our glibc is too old.
+  FUNCTION(strlcat, size_t (*f)(char*, const char*, size_t));
+  FUNCTION(strlcpy, size_t (*f)(char*, const char*, size_t));
+#endif
   FUNCTION(strlen, size_t (*f)(const char*));
   FUNCTION(strncat, char* (*f)(char*, const char*, size_t));
   FUNCTION(strncmp, int (*f)(const char*, const char*, size_t));
diff --git a/tests/headers/posix/unistd_h.c b/tests/headers/posix/unistd_h.c
index f66609d..e54fbb3 100644
--- a/tests/headers/posix/unistd_h.c
+++ b/tests/headers/posix/unistd_h.c
@@ -221,6 +221,9 @@
   MACRO(_SC_MQ_OPEN_MAX);
   MACRO(_SC_MQ_PRIO_MAX);
   MACRO(_SC_NGROUPS_MAX);
+#if defined(__BIONIC__) // New in POSIX 2024.
+  MACRO(_SC_NSIG);
+#endif
   MACRO(_SC_OPEN_MAX);
   MACRO(_SC_PAGE_SIZE);
   MACRO(_SC_PAGESIZE);
@@ -339,6 +342,9 @@
   FUNCTION(ftruncate, int (*f)(int, off_t));
   FUNCTION(getcwd, char* (*f)(char*, size_t));
   FUNCTION(getegid, gid_t (*f)(void));
+#if !defined(__GLIBC__) // Our glibc is too old.
+  FUNCTION(getentropy, int (*f)(void*, size_t));
+#endif
   FUNCTION(geteuid, uid_t (*f)(void));
   FUNCTION(getgid, gid_t (*f)(void));
   FUNCTION(getgroups, int (*f)(int, gid_t[]));
diff --git a/tests/headers/posix/wchar_h.c b/tests/headers/posix/wchar_h.c
index 48b3b92..26a3473 100644
--- a/tests/headers/posix/wchar_h.c
+++ b/tests/headers/posix/wchar_h.c
@@ -86,6 +86,10 @@
   FUNCTION(wcscspn, size_t (*f)(const wchar_t*, const wchar_t*));
   FUNCTION(wcsdup, wchar_t* (*f)(const wchar_t*));
   FUNCTION(wcsftime, size_t (*f)(wchar_t*, size_t, const wchar_t*, const struct tm*));
+#if !defined(__GLIBC__) // Our glibc is too old.
+  FUNCTION(wcslcat, size_t (*f)(wchar_t*, const wchar_t*, size_t));
+  FUNCTION(wcslcpy, size_t (*f)(wchar_t*, const wchar_t*, size_t));
+#endif
   FUNCTION(wcslen, size_t (*f)(const wchar_t*));
   FUNCTION(wcsncasecmp, int (*f)(const wchar_t*, const wchar_t*, size_t));
   FUNCTION(wcsncasecmp_l, int (*f)(const wchar_t*, const wchar_t*, size_t, locale_t));
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 3143c23..c28a46e 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -1000,6 +1000,9 @@
   VERIFY_SYSCONF_POSITIVE(_SC_EXPR_NEST_MAX);
   VERIFY_SYSCONF_POSITIVE(_SC_LINE_MAX);
   VerifySysconf(_SC_NGROUPS_MAX, "_SC_NGROUPS_MAX", [](long v){return v >= 0 && v <= NGROUPS_MAX;});
+#if defined(__BIONIC__) || defined(_SC_NSIG) // New in POSIX 2024.
+  EXPECT_EQ(NSIG, sysconf(_SC_NSIG));
+#endif
   VERIFY_SYSCONF_POSITIVE(_SC_OPEN_MAX);
   VERIFY_SYSCONF_POSITIVE(_SC_PASS_MAX);
   VERIFY_SYSCONF_POSIX_VERSION(_SC_2_C_BIND);