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);