diff --git a/get-nprocs-inaccurate.patch b/get-nprocs-inaccurate.patch deleted file mode 100644 index d3e178e..0000000 --- a/get-nprocs-inaccurate.patch +++ /dev/null @@ -1,199 +0,0 @@ -From 491f2ef1f0ff849490f374917957018d07ee0586 Mon Sep 17 00:00:00 2001 -From: "Dmitry V. Levin" -Date: Sat, 5 Feb 2022 08:00:00 +0000 -Subject: [PATCH] linux: fix accuracy of get_nprocs and get_nprocs_conf [BZ - #28865] - -get_nprocs() and get_nprocs_conf() use various methods to obtain an -accurate number of processors. Re-introduce __get_nprocs_sched() as -a source of information, and fix the order in which these methods are -used to return the most accurate information. The primary source of -information used in both functions remains unchanged. - -This also changes __get_nprocs_sched() error return value from 2 to 0, -but all its users are already prepared to handle that. - -Old fallback order: - get_nprocs: - /sys/devices/system/cpu/online -> /proc/stat -> 2 - get_nprocs_conf: - /sys/devices/system/cpu/ -> /proc/stat -> 2 - -New fallback order: - get_nprocs: - /sys/devices/system/cpu/online -> /proc/stat -> sched_getaffinity -> 2 - get_nprocs_conf: - /sys/devices/system/cpu/ -> /proc/stat -> sched_getaffinity -> 2 - -Fixes: 342298278e ("linux: Revert the use of sched_getaffinity on get_nproc") -Closes: BZ #28865 -Reviewed-by: Adhemerval Zanella - -(cherry picked from commit e1d32b836410767270a3adf1f82b1a47e6e4cd51) ---- - NEWS | 2 + - sysdeps/unix/sysv/linux/getsysstats.c | 94 ++++++++++++++++++--------- - 2 files changed, 65 insertions(+), 31 deletions(-) - -diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c -index c98c8ce3d4..d1ea074f0d 100644 ---- a/sysdeps/unix/sysv/linux/getsysstats.c -+++ b/sysdeps/unix/sysv/linux/getsysstats.c -@@ -50,9 +50,8 @@ __get_nprocs_sched (void) - is an arbitrary values assuming such systems should be rare and there - is no offline cpus. */ - return max_num_cpus; -- /* Some other error. 2 is conservative (not a uniprocessor system, so -- atomics are needed). */ -- return 2; -+ /* Some other error. */ -+ return 0; - } - - static char * -@@ -108,22 +107,19 @@ next_line (int fd, char *const buffer, char **cp, char **re, - } - - static int --get_nproc_stat (char *buffer, size_t buffer_size) -+get_nproc_stat (void) - { -+ enum { buffer_size = 1024 }; -+ char buffer[buffer_size]; - char *buffer_end = buffer + buffer_size; - char *cp = buffer_end; - char *re = buffer_end; -- -- /* Default to an SMP system in case we cannot obtain an accurate -- number. */ -- int result = 2; -+ int result = 0; - - const int flags = O_RDONLY | O_CLOEXEC; - int fd = __open_nocancel ("/proc/stat", flags); - if (fd != -1) - { -- result = 0; -- - char *l; - while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL) - /* The current format of /proc/stat has all the cpu* entries -@@ -139,8 +135,8 @@ get_nproc_stat (char *buffer, size_t buffer_size) - return result; - } - --int --__get_nprocs (void) -+static int -+get_nprocs_cpu_online (void) - { - enum { buffer_size = 1024 }; - char buffer[buffer_size]; -@@ -179,7 +175,8 @@ __get_nprocs (void) - } - } - -- result += m - n + 1; -+ if (m >= n) -+ result += m - n + 1; - - l = endp; - if (l < re && *l == ',') -@@ -188,28 +185,18 @@ __get_nprocs (void) - while (l < re && *l != '\n'); - - __close_nocancel_nostatus (fd); -- -- if (result > 0) -- return result; - } - -- return get_nproc_stat (buffer, buffer_size); -+ return result; - } --libc_hidden_def (__get_nprocs) --weak_alias (__get_nprocs, get_nprocs) -- - --/* On some architectures it is possible to distinguish between configured -- and active cpus. */ --int --__get_nprocs_conf (void) -+static int -+get_nprocs_cpu (void) - { -- /* Try to use the sysfs filesystem. It has actual information about -- online processors. */ -+ int count = 0; - DIR *dir = __opendir ("/sys/devices/system/cpu"); - if (dir != NULL) - { -- int count = 0; - struct dirent64 *d; - - while ((d = __readdir64 (dir)) != NULL) -@@ -224,12 +211,57 @@ __get_nprocs_conf (void) - - __closedir (dir); - -- return count; - } -+ return count; -+} - -- enum { buffer_size = 1024 }; -- char buffer[buffer_size]; -- return get_nproc_stat (buffer, buffer_size); -+static int -+get_nprocs_fallback (void) -+{ -+ int result; -+ -+ /* Try /proc/stat first. */ -+ result = get_nproc_stat (); -+ if (result != 0) -+ return result; -+ -+ /* Try sched_getaffinity. */ -+ result = __get_nprocs_sched (); -+ if (result != 0) -+ return result; -+ -+ /* We failed to obtain an accurate number. Be conservative: return -+ the smallest number meaning that this is not a uniprocessor system, -+ so atomics are needed. */ -+ return 2; -+} -+ -+int -+__get_nprocs (void) -+{ -+ /* Try /sys/devices/system/cpu/online first. */ -+ int result = get_nprocs_cpu_online (); -+ if (result != 0) -+ return result; -+ -+ /* Fall back to /proc/stat and sched_getaffinity. */ -+ return get_nprocs_fallback (); -+} -+libc_hidden_def (__get_nprocs) -+weak_alias (__get_nprocs, get_nprocs) -+ -+/* On some architectures it is possible to distinguish between configured -+ and active cpus. */ -+int -+__get_nprocs_conf (void) -+{ -+ /* Try /sys/devices/system/cpu/ first. */ -+ int result = get_nprocs_cpu (); -+ if (result != 0) -+ return result; -+ -+ /* Fall back to /proc/stat and sched_getaffinity. */ -+ return get_nprocs_fallback (); - } - libc_hidden_def (__get_nprocs_conf) - weak_alias (__get_nprocs_conf, get_nprocs_conf) --- -2.35.0 - diff --git a/get-nprocs-sched-uninit-read.patch b/get-nprocs-sched-uninit-read.patch deleted file mode 100644 index 3fef9f8..0000000 --- a/get-nprocs-sched-uninit-read.patch +++ /dev/null @@ -1,33 +0,0 @@ -From a2f1675634b3513c09c38e55e6766e8c05768b1f Mon Sep 17 00:00:00 2001 -From: Gleb Fotengauer-Malinovskiy -Date: Tue, 1 Feb 2022 22:39:02 +0000 -Subject: [PATCH] linux: __get_nprocs_sched: do not feed CPU_COUNT_S with - garbage [BZ #28850] - -Pass the actual number of bytes returned by the kernel. - -Fixes: 33099d72e41c ("linux: Simplify get_nprocs") -Reviewed-by: Dmitry V. Levin - -(cherry picked from commit 97ba273b505763325efd802dc3a9562dbba79579) ---- - NEWS | 1 + - sysdeps/unix/sysv/linux/getsysstats.c | 2 +- - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c -index 4798cc337e..c98c8ce3d4 100644 ---- a/sysdeps/unix/sysv/linux/getsysstats.c -+++ b/sysdeps/unix/sysv/linux/getsysstats.c -@@ -44,7 +44,7 @@ __get_nprocs_sched (void) - int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, cpu_bits_size, - cpu_bits); - if (r > 0) -- return CPU_COUNT_S (cpu_bits_size, (cpu_set_t*) cpu_bits); -+ return CPU_COUNT_S (r, (cpu_set_t*) cpu_bits); - else if (r == -EINVAL) - /* The input buffer is still not enough to store the number of cpus. This - is an arbitrary values assuming such systems should be rare and there --- -2.35.0 - diff --git a/glibc-2.35.tar.xz b/glibc-2.35.tar.xz deleted file mode 100644 index d32b2fc..0000000 --- a/glibc-2.35.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5123732f6b67ccd319305efd399971d58592122bcc2a6518a1bd2510dd0cf52e -size 18165952 diff --git a/glibc-2.35.tar.xz.sig b/glibc-2.35.tar.xz.sig deleted file mode 100644 index 199aed0..0000000 --- a/glibc-2.35.tar.xz.sig +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCAAdFiEEcnNUKzmWLfeymZMUFnkrTqJTQPgFAmH7d7IACgkQFnkrTqJT -QPgoHBAAlQTCY/HD1Hpro1NaUT8nS0zzB1gw13soniPMdBtJvDTOVZhWkOSto1wg -9z5Tr/JmmnYCE6iu8npYRjkFRXTkPu+mazNcVvwTg08bb0LVn0q4IYHCkrJTLfZi -44fiG76SZOkh/+OTvqNfilWX62zJc1SeMIUy4O1OaPfBA4eZ4hjplOSjJLXG3Hu7 -SZAp7yrTjz4qKJ0rWhGqqfGI7OsT34q3bnAWBRtzPFz+OesLgsLthOAik9vyuuTq -KnBumMmGforja2YToNDa1dkRi7iggDRrUrfi0fBraGXNUMab/QcwifV6gt+bQ/gH -CCalirxD1AQZnRQ/3aVAHE3L2u9fZzGIqbGpkCLhY6M35DKQoZTcW9nR3HfHcnZS -jpiPTu+ONiL0DTdqGAssgfYqP3cIQFEaX7XOpN6qldpuK2d8oJ6JbihIbT6yX/fn -3DYvFbJYSVCW+DN9FL1eMHHVP3R2YPoQ6FS5Iud0W6/p9NGPNYLoFrceZD08yms+ -0HrxYiAb8YDgqk7M5eMSXdcaz2+uRCSTjZHZeGKhJK/5/x7LYAoCgvad5oy+K2pR -fdGxIUfVzJ3LrZRk6/7EbaQGYW07gV3uA0aRfdGQ3UL3xBHhQHEnnRDVpRHHsdSI -1mEj5jT7EEBJwEyppTZXOdTFHeV3ZPeC52rwLO0tQDku9Dn4R8U= -=vosd ------END PGP SIGNATURE----- diff --git a/glibc-2.36.tar.xz b/glibc-2.36.tar.xz new file mode 100644 index 0000000..9e28a4f --- /dev/null +++ b/glibc-2.36.tar.xz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c959fea240906226062cb4b1e7ebce71a9f0e3c0836c09e7e3423d434fcfe75 +size 18610836 diff --git a/glibc-2.36.tar.xz.sig b/glibc-2.36.tar.xz.sig new file mode 100644 index 0000000..67d60fb --- /dev/null +++ b/glibc-2.36.tar.xz.sig @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEEcnNUKzmWLfeymZMUFnkrTqJTQPgFAmLoeDoACgkQFnkrTqJT +QPg4aBAAi49jj5b+KYLEPqwqvBL9o9lF6EX66sxmvcTL/ygZcAGFy2Px3sKfZQpC +0cFuVJNGOXJkbFg+jNzK5pPUWx1NLtYYyhHrIvIBYaAJnJsLNNfIullqOI4doJsY +uXczpqAmwvlAwYdlZMLoTYVtxS80Td27gk+cL/Uk8gEbJANu1iL/G3ruKwb42jD9 +dutEFDaTn6tD4rT0yB92rY3UMH7M2SuNertkhO+10utPNMIwEaaIk28Wa+2Q80xc +R+ALx36O4RQ5NWfOCnw3nrusEFd2dAHEI5mwBpjyCDaZ/XA3QuURjHzcT4jWF3Df +HIi5ED1fbVQpG6gM9V7cfay6hwacDtjoDfEhx3vN4m9l4LD7ySrgh0zrfo9EzO6a +prD1OFA+tgWEA1RoQcuoP5WQ0PloLApX758cQd7XhGPkx2vceffpifpxWiSZXVk0 +Y7u6muq2S3/qzQHHu61ERmNpEYesGEZlXLxvuJvosEmssmYAMTLj7tFTPyIppMDw +aOuNX8Qen5ri4bPrBtibAry02n1NTZ/4IAhHc0WbHUMHqZv2BRmXqj0mP48++Jx/ +BDnJynprKf6yfShhp/6bDXue7eLev21VJH/0GQdppU9f7L/CMlQBI55RLf3fEnw+ +pgmojWTrDp7R7TnTEglb2bTdPvbOx4YKNlTUYURcJGexiF5ydVE= +=EyZe +-----END PGP SIGNATURE----- diff --git a/glibc.changes b/glibc.changes index 497be43..9547e99 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,34 @@ +------------------------------------------------------------------- +Tue Aug 2 07:41:38 UTC 2022 - Andreas Schwab + +- Update to glibc 2.36 + Major new features: + * Support for DT_RELR relative relocation format has been added to + glibc + * On Linux, the pidfd_open, pidfd_getfd, and pidfd_send_signal functions + have been added + * On Linux, the process_madvise function has been added + * On Linux, the process_mrelease function has been added + * The “no-aaaa” DNS stub resolver option has been added + * On Linux, the fsopen, fsmount, move_mount, fsconfig, fspick, open_tree, + and mount_setattr have been added + * localedef now accepts locale definition files encoded in UTF-8 + * Support for the mbrtoc8 and c8rtomb multibyte/UTF-8 character conversion + functions has been added per the ISO C2X N2653 and C++20 P0482R6 proposals + * The functions arc4random, arc4random_buf, and arc4random_uniform have been + added + Deprecated and removed features, and other changes affecting compatibility: + * Support for prelink will be removed in the next release + * The Linux kernel version check has been removed along with the + LD_ASSUME_KERNEL environment variable + * On Linux, The LD_LIBRARY_VERSION environment variable has been removed +- get-nprocs-sched-uninit-read.patch, get-nprocs-inaccurate.patch, + strcmp-rtm-fallback.path, pt-load-invalid-hole.patch, + localedef-ld-monetary.patch, nptl-spurious-eintr.patch, + strncpy-power9-vsx.patch, nptl-cleanup-async-restore.patch, + read-chk-cancel.patch, wcrtomb-fortify.patch, + nptl-cleanup-async-restore-2.patch: Removed + ------------------------------------------------------------------- Thu Jul 14 11:21:34 UTC 2022 - Andreas Schwab diff --git a/glibc.spec b/glibc.spec index 3ac3158..6bfede0 100644 --- a/glibc.spec +++ b/glibc.spec @@ -93,43 +93,6 @@ ExcludeArch: %{cross_arch} %define name_suffix -%{flavor}-src %endif -Name: glibc%{name_suffix} -Summary: Standard Shared Libraries (from the GNU C Library) -License: GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.1-or-later WITH GCC-exception-2.0 -Group: System/Libraries -BuildRequires: audit-devel -BuildRequires: bison -BuildRequires: fdupes -BuildRequires: libcap-devel -BuildRequires: libselinux-devel -BuildRequires: makeinfo -BuildRequires: python3-base -BuildRequires: shadow -BuildRequires: systemd-rpm-macros -BuildRequires: systemtap-headers -BuildRequires: xz -%if %{build_testsuite} -BuildRequires: gcc-c++ -BuildRequires: gdb -BuildRequires: glibc-devel-static -BuildRequires: libidn2-0 -BuildRequires: libstdc++-devel -BuildRequires: python3-pexpect -%endif -%if %{build_utils} -BuildRequires: gd-devel -BuildRequires: libpng-devel -BuildRequires: zlib-devel -%endif -%if %{build_cross} -BuildRequires: cross-%{cross_arch}-gcc%{gcc_version}-bootstrap -BuildRequires: cross-%{cross_arch}-linux-glibc-devel -%endif -%if "%flavor" == "i686" -ExclusiveArch: i586 i686 -BuildArch: i686 -%endif - %define __filter_GLIBC_PRIVATE 1 %ifarch i686 # For i686 let's only build what's different from i586, so @@ -170,10 +133,14 @@ BuildArch: i686 %define enablekernel 4.15 %endif -Version: 2.35 +Name: glibc%{name_suffix} +Summary: Standard Shared Libraries (from the GNU C Library) +License: GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.1-or-later WITH GCC-exception-2.0 +Group: System/Libraries +Version: 2.36 Release: 0 %if !%{build_snapshot} -%define git_id f94f6d8a35 +%define git_id c804cd1c00 %define libversion %version %else %define git_id %(echo %version | sed 's/.*\.g//') @@ -228,7 +195,38 @@ Provides: rtld(GNU_HASH) Requires: glibc = %{version} %endif BuildRoot: %{_tmppath}/%{name}-%{version}-build -# +BuildRequires: audit-devel +BuildRequires: bison +BuildRequires: fdupes +BuildRequires: libcap-devel +BuildRequires: libselinux-devel +BuildRequires: makeinfo +BuildRequires: python3-base +BuildRequires: shadow +BuildRequires: systemd-rpm-macros +BuildRequires: systemtap-headers +BuildRequires: xz +%if %{build_testsuite} +BuildRequires: gcc-c++ +BuildRequires: gdb +BuildRequires: glibc-devel-static +BuildRequires: libidn2-0 +BuildRequires: libstdc++-devel +BuildRequires: python3-pexpect +%endif +%if %{build_utils} +BuildRequires: gd-devel +BuildRequires: libpng-devel +BuildRequires: zlib-devel +%endif +%if %{build_cross} +BuildRequires: cross-%{cross_arch}-gcc%{gcc_version}-bootstrap +BuildRequires: cross-%{cross_arch}-linux-glibc-devel +%endif +%if "%flavor" == "i686" +ExclusiveArch: i586 i686 +BuildArch: i686 +%endif ### # Patches are ordered in the following groups: @@ -283,28 +281,6 @@ Patch306: glibc-fix-double-loopback.diff ### # Patches from upstream ### -# PATCH-FIX-UPSTREAM linux: __get_nprocs_sched: do not feed CPU_COUNT_S with garbage (BZ #28850) -Patch1000: get-nprocs-sched-uninit-read.patch -# PATCH-FIX-UPSTREAM linux: fix accuracy of get_nprocs and get_nprocs_conf (BZ #28865) -Patch1001: get-nprocs-inaccurate.patch -# PATCH-FIX-UPSTREAM x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case (BZ #28896) -Patch1002: strcmp-rtm-fallback.path -# PATCH-FIX-UPSTREAM elf: Check invalid hole in PT_LOAD segments (BZ #28838) -Patch1003: pt-load-invalid-hole.patch -# PATCH-FIX-UPSTREAM localedef: Update LC_MONETARY handling (BZ #28845) -Patch1004: localedef-ld-monetary.patch -# PATCH-FIX-UPSTREAM nptl: Handle spurious EINTR when thread cancellation is disabled (BZ #29029) -Patch1005: nptl-spurious-eintr.patch -# PATCH-FIX-UPSTREAM powerpc: Fix VSX register number on __strncpy_power9 (BZ #29197) -Patch1006: strncpy-power9-vsx.patch -# PATCH-FIX-UPSTREAM nptl: Fix __libc_cleanup_pop_restore asynchronous restore (BZ #29214) -Patch1007: nptl-cleanup-async-restore.patch -# PATCH-FIX-UPSTREAM debug: make __read_chk a cancellation point (BZ #29274) -Patch1008: read-chk-cancel.patch -# PATCH-FIX-UPSTREAM wcrtomb: Make behavior POSIX compliant -Patch1009: wcrtomb-fortify.patch -# PATCH-FIX-UPSTREAM nptl: Fix ___pthread_unregister_cancel_restore asynchronous restore (BZ #29214) -Patch1010: nptl-cleanup-async-restore-2.patch ### # Patches awaiting upstream approval @@ -528,18 +504,6 @@ library in a cross compilation setting. %patch304 -p1 %patch306 -p1 -%patch1000 -p1 -%patch1001 -p1 -%patch1002 -p1 -%patch1003 -p1 -%patch1004 -p1 -%patch1005 -p1 -%patch1006 -p1 -%patch1007 -p1 -%patch1008 -p1 -%patch1009 -p1 -%patch1010 -p1 - %patch2000 -p1 %patch2001 -p1 diff --git a/localedef-ld-monetary.patch b/localedef-ld-monetary.patch deleted file mode 100644 index d9ec40a..0000000 --- a/localedef-ld-monetary.patch +++ /dev/null @@ -1,302 +0,0 @@ -From 3feecd80013c822a12d4b01c5c25e155dfbc6e2f Mon Sep 17 00:00:00 2001 -From: Carlos O'Donell -Date: Thu, 3 Feb 2022 16:51:59 -0500 -Subject: [PATCH] localedef: Update LC_MONETARY handling (Bug 28845) - -ISO C17, POSIX Issue 7, and ISO 30112 all allow the char* -types to be empty strings i.e. "", integer or char values to -be -1 or CHAR_MAX respectively, with the exception of -decimal_point which must be non-empty in ISO C. Note that -the defaults for mon_grouping vary, but are functionaly -equivalent e.g. "\177" (no further grouping reuqired) vs. -"" (no grouping defined for all groups). - -We include a broad comment talking about harmonizing ISO C, -POSIX, ISO 30112, and the default C/POSIX locale for glibc. - -We reorder all setting based on locale/categories.def order. - -We soften all missing definitions from errors to warnings when -defaults exist. - -Given that ISO C, POSIX and ISO 30112 allow the empty string -we change LC_MONETARY handling of mon_decimal_point to allow -the empty string. If mon_decimal_point is not defined at all -then we pick the existing legacy glibc default value of - i.e. ".". - -We also set the default for mon_thousands_sep_wc at the -same time as mon_thousands_sep, but this is not a change in -behaviour, it is always either a matching value or L'\0', -but if in the future we change the default to a non-empty -string we would need to update both at the same time. - -Tested on x86_64 and i686 without regressions. -Tested with install-locale-archive target. -Tested with install-locale-files target. - -Reviewed-by: DJ Delorie -(cherry picked from commit 2ab8b74567dc0a9a3c98696e6444881997dd6c49) ---- - locale/programs/ld-monetary.c | 182 +++++++++++++++++++++++++++------- - 1 file changed, 146 insertions(+), 36 deletions(-) - -diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c -index 3b0412b405..18698bbe94 100644 ---- a/locale/programs/ld-monetary.c -+++ b/locale/programs/ld-monetary.c -@@ -196,21 +196,105 @@ No definition for %s category found"), "LC_MONETARY"); - } - } - -+ /* Generally speaking there are 3 standards the define the default, -+ warning, and error behaviour of LC_MONETARY. They are ISO/IEC TR 30112, -+ ISO/IEC 9899:2018 (ISO C17), and POSIX.1-2017. Within 30112 we have the -+ definition of a standard i18n FDCC-set, which for LC_MONETARY has the -+ following default values: -+ int_curr_symbol "" -+ currency_symbol "" -+ mon_decimal_point "" i.e. "," -+ mon_thousand_sep "" -+ mon_grouping "\177" i.e. CHAR_MAX -+ positive_sign "" -+ negative_sign "" i.e. "." -+ int_frac_digits -1 -+ frac_digits -1 -+ p_cs_precedes -1 -+ p_sep_by_space -1 -+ n_cs_precedes -1 -+ n_sep_by_space -1 -+ p_sign_posn -1 -+ n_sign_posn -1 -+ Under 30112 a keyword that is not provided implies an empty string "" -+ for string values or a -1 for integer values, and indicates the value -+ is unspecified with no default implied. No errors are considered. -+ The exception is mon_grouping which is a string with a terminating -+ CHAR_MAX. -+ For POSIX Issue 7 we have: -+ https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html -+ and again values not provided default to "" or -1, and indicate the value -+ is not available to the locale. The exception is mon_grouping which is -+ a string with a terminating CHAR_MAX. For the POSIX locale the values of -+ LC_MONETARY should be: -+ int_curr_symbol "" -+ currency_symbol "" -+ mon_decimal_point "" -+ mon_thousands_sep "" -+ mon_grouping "\177" i.e. CHAR_MAX -+ positive_sign "" -+ negative_sign "" -+ int_frac_digits -1 -+ frac_digits -1 -+ p_cs_precedes -1 -+ p_sep_by_space -1 -+ n_cs_precedes -1 -+ n_sep_by_space -1 -+ p_sign_posn -1 -+ n_sign_posn -1 -+ int_p_cs_precedes -1 -+ int_p_sep_by_space -1 -+ int_n_cs_precedes -1 -+ int_n_sep_by_space -1 -+ int_p_sign_posn -1 -+ int_n_sign_posn -1 -+ Like with 30112, POSIX also considers no error if the keywords are -+ missing, only that if the cateory as a whole is missing the referencing -+ of the category results in unspecified behaviour. -+ For ISO C17 there is no default value provided, but the localeconv -+ specification in 7.11.2.1 admits that members of char * type may point -+ to "" to indicate a value is not available or is of length zero. -+ The exception is decimal_point (not mon_decimal_point) which must be a -+ defined non-empty string. The values of char, which are generally -+ mapped to integer values in 30112 and POSIX, must be non-negative -+ numbers that map to CHAR_MAX when a value is not available in the -+ locale. -+ In ISO C17 for the "C" locale all values are empty strings "", or -+ CHAR_MAX, with the exception of decimal_point which is "." (defined -+ in LC_NUMERIC). ISO C17 makes no exception for mon_grouping like -+ 30112 and POSIX, but a value of "" is functionally equivalent to -+ "\177" since neither defines a grouping (though the latter terminates -+ the grouping). -+ -+ Lastly, we must consider the legacy C/POSIX locale that implemented -+ as a builtin in glibc and wether a default value mapping to the -+ C/POSIX locale may benefit the user from a compatibility perspective. -+ -+ Thus given 30112, POSIX, ISO C, and the builtin C/POSIX locale we -+ need to pick appropriate defaults below. */ -+ -+ /* The members of LC_MONETARY are handled in the order of their definition -+ in locale/categories.def. Please keep them in that order. */ -+ -+ /* The purpose of TEST_ELEM is to define a default value for the fields -+ in the category if the field was not defined in the cateory. If the -+ category was present but we didn't see a definition for the field then -+ we also issue a warning, otherwise the only warning you get is the one -+ earlier when a default category is created (completely missing category). -+ This missing field warning is glibc-specific since no standard requires -+ this warning, but we consider it valuable to print a warning for all -+ missing fields in the category. */ - #define TEST_ELEM(cat, initval) \ - if (monetary->cat == NULL) \ - { \ - if (! nothing) \ -- record_error (0, 0, _("%s: field `%s' not defined"), \ -- "LC_MONETARY", #cat); \ -+ record_warning (_("%s: field `%s' not defined"), \ -+ "LC_MONETARY", #cat); \ - monetary->cat = initval; \ - } - -+ /* Keyword: int_curr_symbol. */ - TEST_ELEM (int_curr_symbol, ""); -- TEST_ELEM (currency_symbol, ""); -- TEST_ELEM (mon_thousands_sep, ""); -- TEST_ELEM (positive_sign, ""); -- TEST_ELEM (negative_sign, ""); -- - /* The international currency symbol must come from ISO 4217. */ - if (monetary->int_curr_symbol != NULL) - { -@@ -247,41 +331,63 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"), - } - } - -- /* The decimal point must not be empty. This is not said explicitly -- in POSIX but ANSI C (ISO/IEC 9899) says in 4.4.2.1 it has to be -- != "". */ -+ /* Keyword: currency_symbol */ -+ TEST_ELEM (currency_symbol, ""); -+ -+ /* Keyword: mon_decimal_point */ -+ /* ISO C17 7.11.2.1.3 explicitly allows mon_decimal_point to be the -+ empty string e.g. "". This indicates the value is not available in the -+ current locale or is of zero length. However, if the value was never -+ defined then we issue a warning and use a glibc-specific default. ISO -+ 30112 in the i18n FDCC-Set uses ",", and POSIX Issue 7 in the -+ POSIX locale uses "". It is specific to glibc that the default is -+ "."; we retain this existing behaviour for backwards compatibility. */ - if (monetary->mon_decimal_point == NULL) - { - if (! nothing) -- record_error (0, 0, _("%s: field `%s' not defined"), -- "LC_MONETARY", "mon_decimal_point"); -+ record_warning (_("%s: field `%s' not defined, using defaults"), -+ "LC_MONETARY", "mon_decimal_point"); - monetary->mon_decimal_point = "."; - monetary->mon_decimal_point_wc = L'.'; - } -- else if (monetary->mon_decimal_point[0] == '\0' && ! be_quiet && ! nothing) -+ -+ /* Keyword: mon_thousands_sep */ -+ if (monetary->mon_thousands_sep == NULL) - { -- record_error (0, 0, _("\ --%s: value for field `%s' must not be an empty string"), -- "LC_MONETARY", "mon_decimal_point"); -+ if (! nothing) -+ record_warning (_("%s: field `%s' not defined, using defaults"), -+ "LC_MONETARY", "mon_thousands_sep"); -+ monetary->mon_thousands_sep = ""; -+ monetary->mon_thousands_sep_wc = L'\0'; - } - -+ /* Keyword: mon_grouping */ - if (monetary->mon_grouping_len == 0) - { - if (! nothing) -- record_error (0, 0, _("%s: field `%s' not defined"), -- "LC_MONETARY", "mon_grouping"); -- -+ record_warning (_("%s: field `%s' not defined"), -+ "LC_MONETARY", "mon_grouping"); -+ /* Missing entries are given 1 element in their bytearray with -+ a value of CHAR_MAX which indicates that "No further grouping -+ is to be performed" (functionally equivalent to ISO C's "C" -+ locale default of ""). */ - monetary->mon_grouping = (char *) "\177"; - monetary->mon_grouping_len = 1; - } - -+ /* Keyword: positive_sign */ -+ TEST_ELEM (positive_sign, ""); -+ -+ /* Keyword: negative_sign */ -+ TEST_ELEM (negative_sign, ""); -+ - #undef TEST_ELEM - #define TEST_ELEM(cat, min, max, initval) \ - if (monetary->cat == -2) \ - { \ - if (! nothing) \ -- record_error (0, 0, _("%s: field `%s' not defined"), \ -- "LC_MONETARY", #cat); \ -+ record_warning (_("%s: field `%s' not defined"), \ -+ "LC_MONETARY", #cat); \ - monetary->cat = initval; \ - } \ - else if ((monetary->cat < min || monetary->cat > max) \ -@@ -300,16 +406,11 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"), - TEST_ELEM (p_sign_posn, -1, 4, -1); - TEST_ELEM (n_sign_posn, -1, 4, -1); - -- /* The non-POSIX.2 extensions are optional. */ -- if (monetary->duo_int_curr_symbol == NULL) -- monetary->duo_int_curr_symbol = monetary->int_curr_symbol; -- if (monetary->duo_currency_symbol == NULL) -- monetary->duo_currency_symbol = monetary->currency_symbol; -- -- if (monetary->duo_int_frac_digits == -2) -- monetary->duo_int_frac_digits = monetary->int_frac_digits; -- if (monetary->duo_frac_digits == -2) -- monetary->duo_frac_digits = monetary->frac_digits; -+ /* Keyword: crncystr */ -+ monetary->crncystr = (char *) xmalloc (strlen (monetary->currency_symbol) -+ + 2); -+ monetary->crncystr[0] = monetary->p_cs_precedes ? '-' : '+'; -+ strcpy (&monetary->crncystr[1], monetary->currency_symbol); - - #undef TEST_ELEM - #define TEST_ELEM(cat, alt, min, max) \ -@@ -327,6 +428,17 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"), - TEST_ELEM (int_p_sign_posn, p_sign_posn, -1, 4); - TEST_ELEM (int_n_sign_posn, n_sign_posn, -1, 4); - -+ /* The non-POSIX.2 extensions are optional. */ -+ if (monetary->duo_int_curr_symbol == NULL) -+ monetary->duo_int_curr_symbol = monetary->int_curr_symbol; -+ if (monetary->duo_currency_symbol == NULL) -+ monetary->duo_currency_symbol = monetary->currency_symbol; -+ -+ if (monetary->duo_int_frac_digits == -2) -+ monetary->duo_int_frac_digits = monetary->int_frac_digits; -+ if (monetary->duo_frac_digits == -2) -+ monetary->duo_frac_digits = monetary->frac_digits; -+ - TEST_ELEM (duo_p_cs_precedes, p_cs_precedes, -1, 1); - TEST_ELEM (duo_p_sep_by_space, p_sep_by_space, -1, 2); - TEST_ELEM (duo_n_cs_precedes, n_cs_precedes, -1, 1); -@@ -349,17 +461,15 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"), - if (monetary->duo_valid_to == 0) - monetary->duo_valid_to = 99991231; - -+ /* Keyword: conversion_rate */ - if (monetary->conversion_rate[0] == 0) - { - monetary->conversion_rate[0] = 1; - monetary->conversion_rate[1] = 1; - } - -- /* Create the crncystr entry. */ -- monetary->crncystr = (char *) xmalloc (strlen (monetary->currency_symbol) -- + 2); -- monetary->crncystr[0] = monetary->p_cs_precedes ? '-' : '+'; -- strcpy (&monetary->crncystr[1], monetary->currency_symbol); -+ /* A value for monetary-decimal-point-wc was set when -+ monetary_decimal_point was set, likewise for monetary-thousands-sep-wc. */ - } - - --- -2.35.0 - diff --git a/nptl-cleanup-async-restore-2.patch b/nptl-cleanup-async-restore-2.patch deleted file mode 100644 index 9d8fcb0..0000000 --- a/nptl-cleanup-async-restore-2.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 51e2d3b53bd08a21e5a9a4ed095abd2c61f622bc Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Wed, 13 Jul 2022 10:37:32 -0300 -Subject: [PATCH] nptl: Fix ___pthread_unregister_cancel_restore asynchronous - restore - -This was due a wrong revert done on 404656009b459658. - -Checked on x86_64-linux-gnu and i686-linux-gnu. - -(cherry picked from commit f27e5e21787abc9f719879af47687221aa1027b3) ---- - nptl/cleanup_defer.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/nptl/cleanup_defer.c b/nptl/cleanup_defer.c -index eb0bc77740..4e864ead32 100644 ---- a/nptl/cleanup_defer.c -+++ b/nptl/cleanup_defer.c -@@ -71,7 +71,7 @@ ___pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf) - return; - - int cancelhandling = atomic_load_relaxed (&self->cancelhandling); -- if (cancelhandling & CANCELTYPE_BITMASK) -+ if ((cancelhandling & CANCELTYPE_BITMASK) == 0) - { - int newval; - do --- -2.37.1 - diff --git a/nptl-cleanup-async-restore.patch b/nptl-cleanup-async-restore.patch deleted file mode 100644 index 1ba124a..0000000 --- a/nptl-cleanup-async-restore.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 97dd8b3f705b23de1f84713082b631189084a33b Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 31 May 2022 17:13:35 -0300 -Subject: [PATCH] nptl: Fix __libc_cleanup_pop_restore asynchronous restore - (BZ#29214) - -This was due a wrong revert done on 404656009b459658. - -Checked on x86_64-linux-gnu. - -(cherry picked from commit c7d36dcecc08a29825175f65c4ee873ff3177a23) ---- - NEWS | 1 + - nptl/libc-cleanup.c | 3 +- - sysdeps/pthread/Makefile | 1 + - sysdeps/pthread/tst-cancel30.c | 82 ++++++++++++++++++++++++++++++++++ - 4 files changed, 86 insertions(+), 1 deletion(-) - create mode 100644 sysdeps/pthread/tst-cancel30.c - -diff --git a/nptl/libc-cleanup.c b/nptl/libc-cleanup.c -index c4a83591bf..2ce59388d4 100644 ---- a/nptl/libc-cleanup.c -+++ b/nptl/libc-cleanup.c -@@ -57,7 +57,8 @@ __libc_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer) - THREAD_SETMEM (self, cleanup, buffer->__prev); - - int cancelhandling = atomic_load_relaxed (&self->cancelhandling); -- if (cancelhandling & CANCELTYPE_BITMASK) -+ if (buffer->__canceltype != PTHREAD_CANCEL_DEFERRED -+ && (cancelhandling & CANCELTYPE_BITMASK) == 0) - { - int newval; - do -diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile -index c725586308..3a505c5f99 100644 ---- a/sysdeps/pthread/Makefile -+++ b/sysdeps/pthread/Makefile -@@ -126,6 +126,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ - tst-pthread-raise-blocked-self \ - tst-pthread_kill-exited \ - tst-pthread_kill-exiting \ -+ tst-cancel30 \ - # tests - - tests-time64 := \ -diff --git a/sysdeps/pthread/tst-cancel30.c b/sysdeps/pthread/tst-cancel30.c -new file mode 100644 -index 0000000000..e08392f968 ---- /dev/null -+++ b/sysdeps/pthread/tst-cancel30.c -@@ -0,0 +1,82 @@ -+/* Check if printf like functions does not disable asynchronous cancellation -+ mode (BZ#29214). -+ -+ Copyright (C) 2022 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+static pthread_barrier_t b; -+ -+static void * -+tf (void *arg) -+{ -+ int old; -+ -+ TEST_COMPARE (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL), 0); -+ -+ TEST_COMPARE (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old), 0); -+ TEST_COMPARE (old, PTHREAD_CANCEL_ASYNCHRONOUS); -+ -+ /* Check if internal lock cleanup routines restore the cancellation type -+ correctly. */ -+ printf ("...\n"); -+ TEST_COMPARE (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old), 0); -+ TEST_COMPARE (old, PTHREAD_CANCEL_ASYNCHRONOUS); -+ -+ xpthread_barrier_wait (&b); -+ -+ /* Wait indefinitely for cancellation, which only works if asynchronous -+ cancellation is enabled. */ -+#ifdef SYS_pause -+ syscall (SYS_pause); -+#elif defined SYS_ppoll || defined SYS_ppoll_time64 -+# ifndef SYS_ppoll_time64 -+# define SYS_ppoll_time64 SYS_ppoll -+# endif -+ syscall (SYS_ppoll_time64, NULL, 0, NULL, NULL); -+#else -+ for (;;); -+#endif -+ -+ return 0; -+} -+ -+static int -+do_test (void) -+{ -+ xpthread_barrier_init (&b, NULL, 2); -+ -+ pthread_t th = xpthread_create (NULL, tf, NULL); -+ -+ xpthread_barrier_wait (&b); -+ -+ xpthread_cancel (th); -+ -+ void *status = xpthread_join (th); -+ TEST_VERIFY (status == PTHREAD_CANCELED); -+ -+ return 0; -+} -+ -+/* There is no need to wait full TIMEOUT if asynchronous is not working. */ -+#define TIMEOUT 3 -+#include --- -2.35.3 - diff --git a/nptl-spurious-eintr.patch b/nptl-spurious-eintr.patch deleted file mode 100644 index 4b3a0ea..0000000 --- a/nptl-spurious-eintr.patch +++ /dev/null @@ -1,856 +0,0 @@ -From ba9c42ac0e265bf1e4ec1075fa20e7166fda8bfc Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Wed, 6 Apr 2022 12:24:42 -0300 -Subject: [PATCH] nptl: Handle spurious EINTR when thread cancellation is - disabled (BZ#29029) - -Some Linux interfaces never restart after being interrupted by a signal -handler, regardless of the use of SA_RESTART [1]. It means that for -pthread cancellation, if the target thread disables cancellation with -pthread_setcancelstate and calls such interfaces (like poll or select), -it should not see spurious EINTR failures due the internal SIGCANCEL. - -However recent changes made pthread_cancel to always sent the internal -signal, regardless of the target thread cancellation status or type. -To fix it, the previous semantic is restored, where the cancel signal -is only sent if the target thread has cancelation enabled in -asynchronous mode. - -The cancel state and cancel type is moved back to cancelhandling -and atomic operation are used to synchronize between threads. The -patch essentially revert the following commits: - - 8c1c0aae20 nptl: Move cancel type out of cancelhandling - 2b51742531 nptl: Move cancel state out of cancelhandling - 26cfbb7162 nptl: Remove CANCELING_BITMASK - -However I changed the atomic operation to follow the internal C11 -semantic and removed the MACRO usage, it simplifies a bit the -resulting code (and removes another usage of the old atomic macros). - -Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, -and powerpc64-linux-gnu. - -[1] https://man7.org/linux/man-pages/man7/signal.7.html - -Reviewed-by: Florian Weimer -Tested-by: Aurelien Jarno - -(cherry-picked from commit 404656009b459658138ed1bd18f3c6cf3863e6a6) ---- - NEWS | 2 + - manual/process.texi | 3 +- - nptl/allocatestack.c | 2 - - nptl/cancellation.c | 50 ++++++-- - nptl/cleanup_defer.c | 42 ++++++- - nptl/descr.h | 41 +++++-- - nptl/libc-cleanup.c | 39 ++++++- - nptl/pthread_cancel.c | 110 +++++++++++++----- - nptl/pthread_join_common.c | 7 +- - nptl/pthread_setcancelstate.c | 26 ++++- - nptl/pthread_setcanceltype.c | 31 ++++- - nptl/pthread_testcancel.c | 9 +- - sysdeps/nptl/dl-tls_init_tp.c | 3 - - sysdeps/nptl/pthreadP.h | 2 +- - sysdeps/pthread/Makefile | 1 + - sysdeps/pthread/tst-cancel29.c | 207 +++++++++++++++++++++++++++++++++ - 16 files changed, 484 insertions(+), 91 deletions(-) - create mode 100644 sysdeps/pthread/tst-cancel29.c - -diff --git a/manual/process.texi b/manual/process.texi -index 28c9531f42..9307379194 100644 ---- a/manual/process.texi -+++ b/manual/process.texi -@@ -68,8 +68,7 @@ until the subprogram terminates before you can do anything else. - @c CLEANUP_HANDLER @ascuplugin @ascuheap @acsmem - @c libc_cleanup_region_start @ascuplugin @ascuheap @acsmem - @c pthread_cleanup_push_defer @ascuplugin @ascuheap @acsmem --@c __pthread_testcancel @ascuplugin @ascuheap @acsmem --@c CANCEL_ENABLED_AND_CANCELED ok -+@c cancel_enabled_and_canceled @ascuplugin @ascuheap @acsmem - @c do_cancel @ascuplugin @ascuheap @acsmem - @c cancel_handler ok - @c kill syscall ok -diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c -index 34a33164ff..01a282f3f6 100644 ---- a/nptl/allocatestack.c -+++ b/nptl/allocatestack.c -@@ -119,8 +119,6 @@ get_cached_stack (size_t *sizep, void **memp) - - /* Cancellation handling is back to the default. */ - result->cancelhandling = 0; -- result->cancelstate = PTHREAD_CANCEL_ENABLE; -- result->canceltype = PTHREAD_CANCEL_DEFERRED; - result->cleanup = NULL; - result->setup_failed = 0; - -diff --git a/nptl/cancellation.c b/nptl/cancellation.c -index 8d54a6add1..f4b08902b2 100644 ---- a/nptl/cancellation.c -+++ b/nptl/cancellation.c -@@ -30,19 +30,26 @@ int - __pthread_enable_asynccancel (void) - { - struct pthread *self = THREAD_SELF; -+ int oldval = atomic_load_relaxed (&self->cancelhandling); - -- int oldval = THREAD_GETMEM (self, canceltype); -- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_ASYNCHRONOUS); -+ while (1) -+ { -+ int newval = oldval | CANCELTYPE_BITMASK; - -- int ch = THREAD_GETMEM (self, cancelhandling); -+ if (newval == oldval) -+ break; - -- if (self->cancelstate == PTHREAD_CANCEL_ENABLE -- && (ch & CANCELED_BITMASK) -- && !(ch & EXITING_BITMASK) -- && !(ch & TERMINATED_BITMASK)) -- { -- THREAD_SETMEM (self, result, PTHREAD_CANCELED); -- __do_cancel (); -+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling, -+ &oldval, newval)) -+ { -+ if (cancel_enabled_and_canceled_and_async (newval)) -+ { -+ self->result = PTHREAD_CANCELED; -+ __do_cancel (); -+ } -+ -+ break; -+ } - } - - return oldval; -@@ -56,10 +63,29 @@ __pthread_disable_asynccancel (int oldtype) - { - /* If asynchronous cancellation was enabled before we do not have - anything to do. */ -- if (oldtype == PTHREAD_CANCEL_ASYNCHRONOUS) -+ if (oldtype & CANCELTYPE_BITMASK) - return; - - struct pthread *self = THREAD_SELF; -- self->canceltype = PTHREAD_CANCEL_DEFERRED; -+ int newval; -+ int oldval = atomic_load_relaxed (&self->cancelhandling); -+ do -+ { -+ newval = oldval & ~CANCELTYPE_BITMASK; -+ } -+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling, -+ &oldval, newval)); -+ -+ /* We cannot return when we are being canceled. Upon return the -+ thread might be things which would have to be undone. The -+ following loop should loop until the cancellation signal is -+ delivered. */ -+ while (__glibc_unlikely ((newval & (CANCELING_BITMASK | CANCELED_BITMASK)) -+ == CANCELING_BITMASK)) -+ { -+ futex_wait_simple ((unsigned int *) &self->cancelhandling, newval, -+ FUTEX_PRIVATE); -+ newval = atomic_load_relaxed (&self->cancelhandling); -+ } - } - libc_hidden_def (__pthread_disable_asynccancel) -diff --git a/nptl/cleanup_defer.c b/nptl/cleanup_defer.c -index f8181a40e8..eb0bc77740 100644 ---- a/nptl/cleanup_defer.c -+++ b/nptl/cleanup_defer.c -@@ -30,9 +30,22 @@ ___pthread_register_cancel_defer (__pthread_unwind_buf_t *buf) - ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); - ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup); - -- /* Disable asynchronous cancellation for now. */ -- ibuf->priv.data.canceltype = THREAD_GETMEM (self, canceltype); -- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_DEFERRED); -+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling); -+ if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK)) -+ { -+ int newval; -+ do -+ { -+ newval = cancelhandling & ~CANCELTYPE_BITMASK; -+ } -+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling, -+ &cancelhandling, -+ newval)); -+ } -+ -+ ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK -+ ? PTHREAD_CANCEL_ASYNCHRONOUS -+ : PTHREAD_CANCEL_DEFERRED); - - /* Store the new cleanup handler info. */ - THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf); -@@ -54,9 +67,26 @@ ___pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf) - - THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev); - -- THREAD_SETMEM (self, canceltype, ibuf->priv.data.canceltype); -- if (ibuf->priv.data.canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) -- __pthread_testcancel (); -+ if (ibuf->priv.data.canceltype == PTHREAD_CANCEL_DEFERRED) -+ return; -+ -+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling); -+ if (cancelhandling & CANCELTYPE_BITMASK) -+ { -+ int newval; -+ do -+ { -+ newval = cancelhandling | CANCELTYPE_BITMASK; -+ } -+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling, -+ &cancelhandling, newval)); -+ -+ if (cancel_enabled_and_canceled (cancelhandling)) -+ { -+ self->result = PTHREAD_CANCELED; -+ __do_cancel (); -+ } -+ } - } - versioned_symbol (libc, ___pthread_unregister_cancel_restore, - __pthread_unregister_cancel_restore, GLIBC_2_34); -diff --git a/nptl/descr.h b/nptl/descr.h -index ea8aca08e6..bb46b5958e 100644 ---- a/nptl/descr.h -+++ b/nptl/descr.h -@@ -279,18 +279,27 @@ struct pthread - - /* Flags determining processing of cancellation. */ - int cancelhandling; -+ /* Bit set if cancellation is disabled. */ -+#define CANCELSTATE_BIT 0 -+#define CANCELSTATE_BITMASK (1 << CANCELSTATE_BIT) -+ /* Bit set if asynchronous cancellation mode is selected. */ -+#define CANCELTYPE_BIT 1 -+#define CANCELTYPE_BITMASK (1 << CANCELTYPE_BIT) -+ /* Bit set if canceling has been initiated. */ -+#define CANCELING_BIT 2 -+#define CANCELING_BITMASK (1 << CANCELING_BIT) - /* Bit set if canceled. */ - #define CANCELED_BIT 3 --#define CANCELED_BITMASK (0x01 << CANCELED_BIT) -+#define CANCELED_BITMASK (1 << CANCELED_BIT) - /* Bit set if thread is exiting. */ - #define EXITING_BIT 4 --#define EXITING_BITMASK (0x01 << EXITING_BIT) -+#define EXITING_BITMASK (1 << EXITING_BIT) - /* Bit set if thread terminated and TCB is freed. */ - #define TERMINATED_BIT 5 --#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT) -+#define TERMINATED_BITMASK (1 << TERMINATED_BIT) - /* Bit set if thread is supposed to change XID. */ - #define SETXID_BIT 6 --#define SETXID_BITMASK (0x01 << SETXID_BIT) -+#define SETXID_BITMASK (1 << SETXID_BIT) - - /* Flags. Including those copied from the thread attribute. */ - int flags; -@@ -390,14 +399,6 @@ struct pthread - /* Indicates whether is a C11 thread created by thrd_creat. */ - bool c11; - -- /* Thread cancel state (PTHREAD_CANCEL_ENABLE or -- PTHREAD_CANCEL_DISABLE). */ -- unsigned char cancelstate; -- -- /* Thread cancel type (PTHREAD_CANCEL_DEFERRED or -- PTHREAD_CANCEL_ASYNCHRONOUS). */ -- unsigned char canceltype; -- - /* Used in __pthread_kill_internal to detected a thread that has - exited or is about to exit. exit_lock must only be acquired - after blocking signals. */ -@@ -417,6 +418,22 @@ struct pthread - (sizeof (struct pthread) - offsetof (struct pthread, end_padding)) - } __attribute ((aligned (TCB_ALIGNMENT))); - -+static inline bool -+cancel_enabled_and_canceled (int value) -+{ -+ return (value & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK -+ | TERMINATED_BITMASK)) -+ == CANCELED_BITMASK; -+} -+ -+static inline bool -+cancel_enabled_and_canceled_and_async (int value) -+{ -+ return ((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK -+ | EXITING_BITMASK | TERMINATED_BITMASK)) -+ == (CANCELTYPE_BITMASK | CANCELED_BITMASK); -+} -+ - /* This yields the pointer that TLS support code calls the thread pointer. */ - #if TLS_TCB_AT_TP - # define TLS_TPADJ(pd) (pd) -diff --git a/nptl/libc-cleanup.c b/nptl/libc-cleanup.c -index cb4c226281..c4a83591bf 100644 ---- a/nptl/libc-cleanup.c -+++ b/nptl/libc-cleanup.c -@@ -26,9 +26,24 @@ __libc_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer) - - buffer->__prev = THREAD_GETMEM (self, cleanup); - -+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling); -+ - /* Disable asynchronous cancellation for now. */ -- buffer->__canceltype = THREAD_GETMEM (self, canceltype); -- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_DEFERRED); -+ if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK)) -+ { -+ int newval; -+ do -+ { -+ newval = cancelhandling & ~CANCELTYPE_BITMASK; -+ } -+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling, -+ &cancelhandling, -+ newval)); -+ } -+ -+ buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK -+ ? PTHREAD_CANCEL_ASYNCHRONOUS -+ : PTHREAD_CANCEL_DEFERRED); - - THREAD_SETMEM (self, cleanup, buffer); - } -@@ -41,8 +56,22 @@ __libc_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer) - - THREAD_SETMEM (self, cleanup, buffer->__prev); - -- THREAD_SETMEM (self, canceltype, buffer->__canceltype); -- if (buffer->__canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) -- __pthread_testcancel (); -+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling); -+ if (cancelhandling & CANCELTYPE_BITMASK) -+ { -+ int newval; -+ do -+ { -+ newval = cancelhandling | CANCELTYPE_BITMASK; -+ } -+ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling, -+ &cancelhandling, newval)); -+ -+ if (cancel_enabled_and_canceled (cancelhandling)) -+ { -+ self->result = PTHREAD_CANCELED; -+ __do_cancel (); -+ } -+ } - } - libc_hidden_def (__libc_cleanup_pop_restore) -diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c -index 7524c7ce4d..c76882e279 100644 ---- a/nptl/pthread_cancel.c -+++ b/nptl/pthread_cancel.c -@@ -42,18 +42,29 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx) - - struct pthread *self = THREAD_SELF; - -- int ch = atomic_load_relaxed (&self->cancelhandling); -- /* Cancelation not enabled, not cancelled, or already exitting. */ -- if (self->cancelstate == PTHREAD_CANCEL_DISABLE -- || (ch & CANCELED_BITMASK) == 0 -- || (ch & EXITING_BITMASK) != 0) -- return; -- -- /* Set the return value. */ -- THREAD_SETMEM (self, result, PTHREAD_CANCELED); -- /* Make sure asynchronous cancellation is still enabled. */ -- if (self->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) -- __do_cancel (); -+ int oldval = atomic_load_relaxed (&self->cancelhandling); -+ while (1) -+ { -+ /* We are canceled now. When canceled by another thread this flag -+ is already set but if the signal is directly send (internally or -+ from another process) is has to be done here. */ -+ int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; -+ -+ if (oldval == newval || (oldval & EXITING_BITMASK) != 0) -+ /* Already canceled or exiting. */ -+ break; -+ -+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling, -+ &oldval, newval)) -+ { -+ self->result = PTHREAD_CANCELED; -+ -+ /* Make sure asynchronous cancellation is still enabled. */ -+ if ((oldval & CANCELTYPE_BITMASK) != 0) -+ /* Run the registered destructors and terminate the thread. */ -+ __do_cancel (); -+ } -+ } - } - - int -@@ -92,29 +103,70 @@ __pthread_cancel (pthread_t th) - } - #endif - -- int oldch = atomic_fetch_or_acquire (&pd->cancelhandling, CANCELED_BITMASK); -- if ((oldch & CANCELED_BITMASK) != 0) -- return 0; -- -- if (pd == THREAD_SELF) -+ /* Some syscalls are never restarted after being interrupted by a signal -+ handler, regardless of the use of SA_RESTART (they always fail with -+ EINTR). So pthread_cancel cannot send SIGCANCEL unless the cancellation -+ is enabled and set as asynchronous (in this case the cancellation will -+ be acted in the cancellation handler instead by the syscall wrapper). -+ Otherwise the target thread is set as 'cancelling' (CANCELING_BITMASK) -+ by atomically setting 'cancelhandling' and the cancelation will be acted -+ upon on next cancellation entrypoing in the target thread. -+ -+ It also requires to atomically check if cancellation is enabled and -+ asynchronous, so both cancellation state and type are tracked on -+ 'cancelhandling'. */ -+ -+ int result = 0; -+ int oldval = atomic_load_relaxed (&pd->cancelhandling); -+ int newval; -+ do - { -- /* A single-threaded process should be able to kill itself, since there -- is nothing in the POSIX specification that says that it cannot. So -- we set multiple_threads to true so that cancellation points get -- executed. */ -- THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); -+ newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; -+ if (oldval == newval) -+ break; -+ -+ /* If the cancellation is handled asynchronously just send a -+ signal. We avoid this if possible since it's more -+ expensive. */ -+ if (cancel_enabled_and_canceled_and_async (newval)) -+ { -+ /* Mark the cancellation as "in progress". */ -+ int newval2 = oldval | CANCELING_BITMASK; -+ if (!atomic_compare_exchange_weak_acquire (&pd->cancelhandling, -+ &oldval, newval2)) -+ continue; -+ -+ if (pd == THREAD_SELF) -+ /* This is not merely an optimization: An application may -+ call pthread_cancel (pthread_self ()) without calling -+ pthread_create, so the signal handler may not have been -+ set up for a self-cancel. */ -+ { -+ pd->result = PTHREAD_CANCELED; -+ if ((newval & CANCELTYPE_BITMASK) != 0) -+ __do_cancel (); -+ } -+ else -+ /* The cancellation handler will take care of marking the -+ thread as canceled. */ -+ result = __pthread_kill_internal (th, SIGCANCEL); -+ -+ break; -+ } -+ -+ /* A single-threaded process should be able to kill itself, since -+ there is nothing in the POSIX specification that says that it -+ cannot. So we set multiple_threads to true so that cancellation -+ points get executed. */ -+ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); - #ifndef TLS_MULTIPLE_THREADS_IN_TCB - __libc_multiple_threads = 1; - #endif -- -- THREAD_SETMEM (pd, result, PTHREAD_CANCELED); -- if (pd->cancelstate == PTHREAD_CANCEL_ENABLE -- && pd->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) -- __do_cancel (); -- return 0; - } -+ while (!atomic_compare_exchange_weak_acquire (&pd->cancelhandling, &oldval, -+ newval)); - -- return __pthread_kill_internal (th, SIGCANCEL); -+ return result; - } - versioned_symbol (libc, __pthread_cancel, pthread_cancel, GLIBC_2_34); - -diff --git a/nptl/pthread_join_common.c b/nptl/pthread_join_common.c -index a8e884f341..ca3245b0af 100644 ---- a/nptl/pthread_join_common.c -+++ b/nptl/pthread_join_common.c -@@ -57,12 +57,9 @@ __pthread_clockjoin_ex (pthread_t threadid, void **thread_return, - if ((pd == self - || (self->joinid == pd - && (pd->cancelhandling -- & (CANCELED_BITMASK | EXITING_BITMASK -+ & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK - | TERMINATED_BITMASK)) == 0)) -- && !(self->cancelstate == PTHREAD_CANCEL_ENABLE -- && (pd->cancelhandling & (CANCELED_BITMASK | EXITING_BITMASK -- | TERMINATED_BITMASK)) -- == CANCELED_BITMASK)) -+ && !cancel_enabled_and_canceled (self->cancelhandling)) - /* This is a deadlock situation. The threads are waiting for each - other to finish. Note that this is a "may" error. To be 100% - sure we catch this error we would have to lock the data -diff --git a/nptl/pthread_setcancelstate.c b/nptl/pthread_setcancelstate.c -index 9905b12e4f..f8edf18fbe 100644 ---- a/nptl/pthread_setcancelstate.c -+++ b/nptl/pthread_setcancelstate.c -@@ -30,9 +30,29 @@ __pthread_setcancelstate (int state, int *oldstate) - - self = THREAD_SELF; - -- if (oldstate != NULL) -- *oldstate = self->cancelstate; -- self->cancelstate = state; -+ int oldval = atomic_load_relaxed (&self->cancelhandling); -+ while (1) -+ { -+ int newval = (state == PTHREAD_CANCEL_DISABLE -+ ? oldval | CANCELSTATE_BITMASK -+ : oldval & ~CANCELSTATE_BITMASK); -+ -+ if (oldstate != NULL) -+ *oldstate = ((oldval & CANCELSTATE_BITMASK) -+ ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE); -+ -+ if (oldval == newval) -+ break; -+ -+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling, -+ &oldval, newval)) -+ { -+ if (cancel_enabled_and_canceled_and_async (newval)) -+ __do_cancel (); -+ -+ break; -+ } -+ } - - return 0; - } -diff --git a/nptl/pthread_setcanceltype.c b/nptl/pthread_setcanceltype.c -index 94e56466de..1307d355c1 100644 ---- a/nptl/pthread_setcanceltype.c -+++ b/nptl/pthread_setcanceltype.c -@@ -28,11 +28,32 @@ __pthread_setcanceltype (int type, int *oldtype) - - volatile struct pthread *self = THREAD_SELF; - -- if (oldtype != NULL) -- *oldtype = self->canceltype; -- self->canceltype = type; -- if (type == PTHREAD_CANCEL_ASYNCHRONOUS) -- __pthread_testcancel (); -+ int oldval = atomic_load_relaxed (&self->cancelhandling); -+ while (1) -+ { -+ int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS -+ ? oldval | CANCELTYPE_BITMASK -+ : oldval & ~CANCELTYPE_BITMASK); -+ -+ if (oldtype != NULL) -+ *oldtype = ((oldval & CANCELTYPE_BITMASK) -+ ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED); -+ -+ if (oldval == newval) -+ break; -+ -+ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling, -+ &oldval, newval)) -+ { -+ if (cancel_enabled_and_canceled_and_async (newval)) -+ { -+ THREAD_SETMEM (self, result, PTHREAD_CANCELED); -+ __do_cancel (); -+ } -+ -+ break; -+ } -+ } - - return 0; - } -diff --git a/nptl/pthread_testcancel.c b/nptl/pthread_testcancel.c -index 13123608e8..b81928c000 100644 ---- a/nptl/pthread_testcancel.c -+++ b/nptl/pthread_testcancel.c -@@ -23,13 +23,10 @@ void - ___pthread_testcancel (void) - { - struct pthread *self = THREAD_SELF; -- int cancelhandling = THREAD_GETMEM (self, cancelhandling); -- if (self->cancelstate == PTHREAD_CANCEL_ENABLE -- && (cancelhandling & CANCELED_BITMASK) -- && !(cancelhandling & EXITING_BITMASK) -- && !(cancelhandling & TERMINATED_BITMASK)) -+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling); -+ if (cancel_enabled_and_canceled (cancelhandling)) - { -- THREAD_SETMEM (self, result, PTHREAD_CANCELED); -+ self->result = PTHREAD_CANCELED; - __do_cancel (); - } - } -diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c -index 1294c91816..53fba774a5 100644 ---- a/sysdeps/nptl/dl-tls_init_tp.c -+++ b/sysdeps/nptl/dl-tls_init_tp.c -@@ -128,7 +128,4 @@ __tls_init_tp (void) - It will be bigger than it actually is, but for unwind.c/pt-longjmp.c - purposes this is good enough. */ - THREAD_SETMEM (pd, stackblock_size, (size_t) __libc_stack_end); -- -- THREAD_SETMEM (pd, cancelstate, PTHREAD_CANCEL_ENABLE); -- THREAD_SETMEM (pd, canceltype, PTHREAD_CANCEL_DEFERRED); - } -diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h -index 708bd92469..601db4ff2b 100644 ---- a/sysdeps/nptl/pthreadP.h -+++ b/sysdeps/nptl/pthreadP.h -@@ -275,7 +275,7 @@ __do_cancel (void) - struct pthread *self = THREAD_SELF; - - /* Make sure we get no more cancellations. */ -- THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT); -+ atomic_bit_set (&self->cancelhandling, EXITING_BIT); - - __pthread_unwind ((__pthread_unwind_buf_t *) - THREAD_GETMEM (self, cleanup_jmp_buf)); -diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile -index c972bd819a..e67db428d9 100644 ---- a/sysdeps/pthread/Makefile -+++ b/sysdeps/pthread/Makefile -@@ -69,6 +69,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ - tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 tst-cancel16 \ - tst-cancel18 tst-cancel19 tst-cancel20 tst-cancel21 \ - tst-cancel22 tst-cancel23 tst-cancel26 tst-cancel27 tst-cancel28 \ -+ tst-cancel29 \ - tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \ - tst-clock1 \ - tst-cond-except \ -diff --git a/sysdeps/pthread/tst-cancel29.c b/sysdeps/pthread/tst-cancel29.c -new file mode 100644 -index 0000000000..4f0d99e002 ---- /dev/null -+++ b/sysdeps/pthread/tst-cancel29.c -@@ -0,0 +1,207 @@ -+/* Check if a thread that disables cancellation and which call functions -+ that might be interrupted by a signal do not see the internal SIGCANCEL. -+ -+ Copyright (C) 2022 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* On Linux some interfaces are never restarted after being interrupted by -+ a signal handler, regardless of the use of SA_RESTART. It means that -+ if asynchronous cancellation is not enabled, the pthread_cancel can not -+ set the internal SIGCANCEL otherwise the interface might see a spurious -+ EINTR failure. */ -+ -+static pthread_barrier_t b; -+ -+/* Cleanup handling test. */ -+static int cl_called; -+static void -+cl (void *arg) -+{ -+ ++cl_called; -+} -+ -+static void * -+tf_sigtimedwait (void *arg) -+{ -+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); -+ xpthread_barrier_wait (&b); -+ -+ int r; -+ pthread_cleanup_push (cl, NULL); -+ -+ sigset_t mask; -+ sigemptyset (&mask); -+ r = sigtimedwait (&mask, NULL, &(struct timespec) { 0, 250000000 }); -+ if (r != -1) -+ return (void*) -1; -+ if (errno != EAGAIN) -+ return (void*) -2; -+ -+ pthread_cleanup_pop (0); -+ return NULL; -+} -+ -+static void * -+tf_poll (void *arg) -+{ -+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); -+ xpthread_barrier_wait (&b); -+ -+ int r; -+ pthread_cleanup_push (cl, NULL); -+ -+ r = poll (NULL, 0, 250); -+ if (r != 0) -+ return (void*) -1; -+ -+ pthread_cleanup_pop (0); -+ return NULL; -+} -+ -+static void * -+tf_ppoll (void *arg) -+{ -+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); -+ -+ xpthread_barrier_wait (&b); -+ -+ int r; -+ pthread_cleanup_push (cl, NULL); -+ -+ r = ppoll (NULL, 0, &(struct timespec) { 0, 250000000 }, NULL); -+ if (r != 0) -+ return (void*) -1; -+ -+ pthread_cleanup_pop (0); -+ return NULL; -+} -+ -+static void * -+tf_select (void *arg) -+{ -+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); -+ xpthread_barrier_wait (&b); -+ -+ int r; -+ pthread_cleanup_push (cl, NULL); -+ -+ r = select (0, NULL, NULL, NULL, &(struct timeval) { 0, 250000 }); -+ if (r != 0) -+ return (void*) -1; -+ -+ pthread_cleanup_pop (0); -+ return NULL; -+} -+ -+static void * -+tf_pselect (void *arg) -+{ -+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); -+ xpthread_barrier_wait (&b); -+ -+ int r; -+ pthread_cleanup_push (cl, NULL); -+ -+ r = pselect (0, NULL, NULL, NULL, &(struct timespec) { 0, 250000000 }, NULL); -+ if (r != 0) -+ return (void*) -1; -+ -+ pthread_cleanup_pop (0); -+ return NULL; -+} -+ -+static void * -+tf_clock_nanosleep (void *arg) -+{ -+ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); -+ xpthread_barrier_wait (&b); -+ -+ int r; -+ pthread_cleanup_push (cl, NULL); -+ -+ r = clock_nanosleep (CLOCK_REALTIME, 0, &(struct timespec) { 0, 250000000 }, -+ NULL); -+ if (r != 0) -+ return (void*) -1; -+ -+ pthread_cleanup_pop (0); -+ return NULL; -+} -+ -+struct cancel_test_t -+{ -+ const char *name; -+ void * (*cf) (void *); -+} tests[] = -+{ -+ { "sigtimedwait", tf_sigtimedwait, }, -+ { "poll", tf_poll, }, -+ { "ppoll", tf_ppoll, }, -+ { "select", tf_select, }, -+ { "pselect", tf_pselect , }, -+ { "clock_nanosleep", tf_clock_nanosleep, }, -+}; -+ -+static int -+do_test (void) -+{ -+ for (int i = 0; i < array_length (tests); i++) -+ { -+ xpthread_barrier_init (&b, NULL, 2); -+ -+ cl_called = 0; -+ -+ pthread_t th = xpthread_create (NULL, tests[i].cf, NULL); -+ -+ xpthread_barrier_wait (&b); -+ -+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 }; -+ while (nanosleep (&ts, &ts) != 0) -+ continue; -+ -+ xpthread_cancel (th); -+ -+ void *status = xpthread_join (th); -+ if (status != NULL) -+ printf ("test '%s' failed: %" PRIdPTR "\n", tests[i].name, -+ (intptr_t) status); -+ TEST_VERIFY (status == NULL); -+ -+ xpthread_barrier_destroy (&b); -+ -+ TEST_COMPARE (cl_called, 0); -+ -+ printf ("in-time cancel test of '%s' successful\n", tests[i].name); -+ } -+ -+ return 0; -+} -+ -+#include --- -2.35.2 - diff --git a/pt-load-invalid-hole.patch b/pt-load-invalid-hole.patch deleted file mode 100644 index f8dd2db..0000000 --- a/pt-load-invalid-hole.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 1dd783fafdbc30bd82e078ccab42b9539d3274a5 Mon Sep 17 00:00:00 2001 -From: "H.J. Lu" -Date: Tue, 15 Feb 2022 06:57:11 -0800 -Subject: [PATCH] elf: Check invalid hole in PT_LOAD segments [BZ #28838] - -Changes in v2: - -1. Update commit log. - -commit 163f625cf9becbb82dfec63a29e566324129c0cd -Author: H.J. Lu -Date: Tue Dec 21 12:35:47 2021 -0800 - - elf: Remove excessive p_align check on PT_LOAD segments [BZ #28688] - -removed the p_align check against the page size. It caused the loader -error or crash on elf/tst-p_align3 when loading elf/tst-p_alignmod3.so, -which has the invalid p_align in PT_LOAD segments, added by - -commit d8d94863ef125a392b929732b37e07dc927fbcd1 -Author: H.J. Lu -Date: Tue Dec 21 13:42:28 2021 -0800 - -The loader failure caused by a negative length passed to __mprotect is -random, depending on architecture and toolchain. Update _dl_map_segments -to detect invalid holes. This fixes BZ #28838. - -Reviewed-by: Florian Weimer -(cherry picked from commit 2c0915cbf570cb9c8a65f1d20a55c5a7238e5b63) ---- - elf/dl-map-segments.h | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h -index 172692b120..fd24cf5d01 100644 ---- a/elf/dl-map-segments.h -+++ b/elf/dl-map-segments.h -@@ -113,6 +113,9 @@ _dl_map_segments (struct link_map *l, int fd, - unallocated. Then jump into the normal segment-mapping loop to - handle the portion of the segment past the end of the file - mapping. */ -+ if (__glibc_unlikely (loadcmds[nloadcmds - 1].mapstart < -+ c->mapend)) -+ return N_("ELF load command address/offset not page-aligned"); - if (__glibc_unlikely - (__mprotect ((caddr_t) (l->l_addr + c->mapend), - loadcmds[nloadcmds - 1].mapstart - c->mapend, --- -2.35.0 - diff --git a/read-chk-cancel.patch b/read-chk-cancel.patch deleted file mode 100644 index 4c9586a..0000000 --- a/read-chk-cancel.patch +++ /dev/null @@ -1,129 +0,0 @@ -From dc30acf20bd635d71cd4c84100e842fdf0429e48 Mon Sep 17 00:00:00 2001 -From: Andreas Schwab -Date: Wed, 22 Jun 2022 13:16:30 +0200 -Subject: [PATCH] debug: make __read_chk a cancellation point (bug 29274) - -The __read_chk function, as the implementation behind the fortified read -function, must be a cancellation point, thus it cannot use INLINE_SYSCALL. ---- - debug/Makefile | 7 ++++++ - debug/read_chk.c | 10 -------- - debug/tst-read-chk-cancel.c | 50 +++++++++++++++++++++++++++++++++++++ - 3 files changed, 57 insertions(+), 10 deletions(-) - create mode 100644 debug/tst-read-chk-cancel.c - -diff --git a/debug/Makefile b/debug/Makefile -index 96029f32ee..456b349c4d 100644 ---- a/debug/Makefile -+++ b/debug/Makefile -@@ -110,6 +110,7 @@ CPPFLAGS-tst-longjmp_chk2.c += -D_FORTIFY_SOURCE=1 - CFLAGS-tst-longjmp_chk3.c += -fexceptions -fasynchronous-unwind-tables - CPPFLAGS-tst-longjmp_chk3.c += -D_FORTIFY_SOURCE=1 - CPPFLAGS-tst-realpath-chk.c += -D_FORTIFY_SOURCE=2 -+CPPFLAGS-tst-read-chk-cancel.c += -D_FORTIFY_SOURCE=2 - - # _FORTIFY_SOURCE tests. - # Auto-generate tests for _FORTIFY_SOURCE for different levels, compilers and -@@ -204,6 +205,10 @@ ifeq ($(have-ssp),yes) - tests += tst-ssp-1 - endif - -+ifeq ($(have-thread-library), yes) -+tests += tst-read-chk-cancel -+endif -+ - ifeq (,$(CXX)) - tests-unsupported = $(tests-cc-chk) - endif -@@ -242,3 +247,5 @@ $(objpfx)xtrace: xtrace.sh - -e 's|@BINDIR@|$(bindir)|' -e 's|@PKGVERSION@|$(PKGVERSION)|' \ - -e 's|@REPORT_BUGS_TO@|$(REPORT_BUGS_TO)|' $^ > $@.new \ - && rm -f $@ && mv $@.new $@ && chmod +x $@ -+ -+$(objpfx)tst-read-chk-cancel: $(shared-thread-library) -diff --git a/debug/read_chk.c b/debug/read_chk.c -index 0cd58db8cb..274b4f93e9 100644 ---- a/debug/read_chk.c -+++ b/debug/read_chk.c -@@ -16,12 +16,6 @@ - . */ - - #include --#include --#ifdef HAVE_INLINED_SYSCALLS --# include --# include --#endif -- - - ssize_t - __read_chk (int fd, void *buf, size_t nbytes, size_t buflen) -@@ -29,9 +23,5 @@ __read_chk (int fd, void *buf, size_t nbytes, size_t buflen) - if (nbytes > buflen) - __chk_fail (); - --#ifdef HAVE_INLINED_SYSCALLS -- return INLINE_SYSCALL (read, 3, fd, buf, nbytes); --#else - return __read (fd, buf, nbytes); --#endif - } -diff --git a/debug/tst-read-chk-cancel.c b/debug/tst-read-chk-cancel.c -new file mode 100644 -index 0000000000..7e06afb596 ---- /dev/null -+++ b/debug/tst-read-chk-cancel.c -@@ -0,0 +1,50 @@ -+/* Test that __read_chk is a cancellation point (BZ #29274) -+ Copyright (C) 2022 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+#include -+ -+static int pipe_fds[2]; -+static pthread_barrier_t barrier; -+ -+static void * -+read_thread (void *n) -+{ -+ xpthread_barrier_wait (&barrier); -+ char c; -+ /* This call should be forwarded to __read_chk because the buffer size -+ is known, but the read length is non-constant. */ -+ if (read (pipe_fds[0], &c, (uintptr_t) n) != 1) -+ return (void *) -1L; -+ return 0; -+} -+ -+static int -+do_test (void) -+{ -+ xpthread_barrier_init (&barrier, 0, 2); -+ xpipe (pipe_fds); -+ pthread_t thr = xpthread_create (0, read_thread, (void *) 1L); -+ xpthread_barrier_wait (&barrier); -+ xpthread_cancel (thr); -+ xpthread_join (thr); -+ return 0; -+} -+ -+#include --- -2.35.3 - diff --git a/strcmp-rtm-fallback.path b/strcmp-rtm-fallback.path deleted file mode 100644 index 74e5c2a..0000000 --- a/strcmp-rtm-fallback.path +++ /dev/null @@ -1,132 +0,0 @@ -From fd412fff6d2bd322ec24ebd13fab196efc6c5506 Mon Sep 17 00:00:00 2001 -From: Noah Goldstein -Date: Tue, 15 Feb 2022 08:18:15 -0600 -Subject: [PATCH] x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case [BZ - #28896] - -In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would -call strcmp-avx2 and wcscmp-avx2 respectively. This would have -not checks around vzeroupper and would trigger spurious -aborts. This commit fixes that. - -test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on -AVX2 machines with and without RTM. - -Co-authored-by: H.J. Lu - -(cherry picked from commit c6272098323153db373f2986c67786ea8c85f1cf) ---- - sysdeps/x86/Makefile | 2 +- - sysdeps/x86/tst-strncmp-rtm.c | 17 ++++++++++++++++- - sysdeps/x86_64/multiarch/strcmp-avx2.S | 2 +- - sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S | 1 + - sysdeps/x86_64/multiarch/strncmp-avx2.S | 1 + - sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S | 2 +- - sysdeps/x86_64/multiarch/wcsncmp-avx2.S | 2 +- - 7 files changed, 22 insertions(+), 5 deletions(-) - -diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile -index 6cf708335c..d110f7b7f2 100644 ---- a/sysdeps/x86/Makefile -+++ b/sysdeps/x86/Makefile -@@ -109,7 +109,7 @@ CFLAGS-tst-memset-rtm.c += -mrtm - CFLAGS-tst-strchr-rtm.c += -mrtm - CFLAGS-tst-strcpy-rtm.c += -mrtm - CFLAGS-tst-strlen-rtm.c += -mrtm --CFLAGS-tst-strncmp-rtm.c += -mrtm -+CFLAGS-tst-strncmp-rtm.c += -mrtm -Wno-error - CFLAGS-tst-strrchr-rtm.c += -mrtm - endif - -diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c -index 09ed6fa0d6..9e20abaacc 100644 ---- a/sysdeps/x86/tst-strncmp-rtm.c -+++ b/sysdeps/x86/tst-strncmp-rtm.c -@@ -16,6 +16,7 @@ - License along with the GNU C Library; if not, see - . */ - -+#include - #include - - #define LOOP 3000 -@@ -45,8 +46,22 @@ function (void) - return 1; - } - -+__attribute__ ((noinline, noclone)) -+static int -+function_overflow (void) -+{ -+ if (strncmp (string1, string2, SIZE_MAX) == 0) -+ return 0; -+ else -+ return 1; -+} -+ - static int - do_test (void) - { -- return do_test_1 ("strncmp", LOOP, prepare, function); -+ int status = do_test_1 ("strncmp", LOOP, prepare, function); -+ if (status != EXIT_SUCCESS) -+ return status; -+ status = do_test_1 ("strncmp", LOOP, prepare, function_overflow); -+ return status; - } -diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S -index 9c73b5899d..cdcb3c5a26 100644 ---- a/sysdeps/x86_64/multiarch/strcmp-avx2.S -+++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S -@@ -95,7 +95,7 @@ ENTRY (STRCMP) - length to bound a valid memory region. In these cases just use - 'wcscmp'. */ - shrq $56, %rcx -- jnz __wcscmp_avx2 -+ jnz OVERFLOW_STRCMP - # endif - /* Convert units: from wide to byte char. */ - shl $2, %RDX_LP -diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S -index 37d1224bb9..68bad365ba 100644 ---- a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S -+++ b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S -@@ -1,3 +1,4 @@ - #define STRCMP __strncmp_avx2_rtm - #define USE_AS_STRNCMP 1 -+#define OVERFLOW_STRCMP __strcmp_avx2_rtm - #include "strcmp-avx2-rtm.S" -diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2.S b/sysdeps/x86_64/multiarch/strncmp-avx2.S -index 1678bcc235..f138e9f1fd 100644 ---- a/sysdeps/x86_64/multiarch/strncmp-avx2.S -+++ b/sysdeps/x86_64/multiarch/strncmp-avx2.S -@@ -1,3 +1,4 @@ - #define STRCMP __strncmp_avx2 - #define USE_AS_STRNCMP 1 -+#define OVERFLOW_STRCMP __strcmp_avx2 - #include "strcmp-avx2.S" -diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S -index 4e88c70cc6..f467582cbe 100644 ---- a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S -+++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S -@@ -1,5 +1,5 @@ - #define STRCMP __wcsncmp_avx2_rtm - #define USE_AS_STRNCMP 1 - #define USE_AS_WCSCMP 1 -- -+#define OVERFLOW_STRCMP __wcscmp_avx2_rtm - #include "strcmp-avx2-rtm.S" -diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S -index 4fa1de4d3f..e9ede522b8 100644 ---- a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S -+++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S -@@ -1,5 +1,5 @@ - #define STRCMP __wcsncmp_avx2 - #define USE_AS_STRNCMP 1 - #define USE_AS_WCSCMP 1 -- -+#define OVERFLOW_STRCMP __wcscmp_avx2 - #include "strcmp-avx2.S" --- -2.35.0 - diff --git a/strncpy-power9-vsx.patch b/strncpy-power9-vsx.patch deleted file mode 100644 index d52faa3..0000000 --- a/strncpy-power9-vsx.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 0a1572b8bb880a63d50a63b2afe4bb67704ac23e Mon Sep 17 00:00:00 2001 -From: Matheus Castanho -Date: Tue, 7 Jun 2022 10:27:26 -0300 -Subject: [PATCH] powerpc: Fix VSX register number on __strncpy_power9 [BZ - #29197] - -__strncpy_power9 initializes VR 18 with zeroes to be used throughout the -code, including when zero-padding the destination string. However, the -v18 reference was mistakenly being used for stxv and stxvl, which take a -VSX vector as operand. The code ended up using the uninitialized VSR 18 -register by mistake. - -Both occurrences have been changed to use the proper VSX number for VR 18 -(i.e. VSR 50). - -Tested on powerpc, powerpc64 and powerpc64le. - -Signed-off-by: Kewen Lin -(cherry picked from commit 0218463dd8265ed937622f88ac68c7d984fe0cfc) ---- - sysdeps/powerpc/powerpc64/le/power9/strncpy.S | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/sysdeps/powerpc/powerpc64/le/power9/strncpy.S b/sysdeps/powerpc/powerpc64/le/power9/strncpy.S -index ae23161316..deb94671cc 100644 ---- a/sysdeps/powerpc/powerpc64/le/power9/strncpy.S -+++ b/sysdeps/powerpc/powerpc64/le/power9/strncpy.S -@@ -352,7 +352,7 @@ L(zero_padding_loop): - cmpldi cr6,r5,16 /* Check if length was reached. */ - ble cr6,L(zero_padding_end) - -- stxv v18,0(r11) -+ stxv 32+v18,0(r11) - addi r11,r11,16 - addi r5,r5,-16 - -@@ -360,7 +360,7 @@ L(zero_padding_loop): - - L(zero_padding_end): - sldi r10,r5,56 /* stxvl wants size in top 8 bits */ -- stxvl v18,r11,r10 /* Partial store */ -+ stxvl 32+v18,r11,r10 /* Partial store */ - blr - - .align 4 --- -2.35.3 - diff --git a/wcrtomb-fortify.patch b/wcrtomb-fortify.patch deleted file mode 100644 index 3de33be..0000000 --- a/wcrtomb-fortify.patch +++ /dev/null @@ -1,224 +0,0 @@ -From 9bcd12d223a8990254b65e2dada54faa5d2742f3 Mon Sep 17 00:00:00 2001 -From: Siddhesh Poyarekar -Date: Fri, 13 May 2022 19:10:15 +0530 -Subject: [PATCH] wcrtomb: Make behavior POSIX compliant - -The GNU implementation of wcrtomb assumes that there are at least -MB_CUR_MAX bytes available in the destination buffer passed to wcrtomb -as the first argument. This is not compatible with the POSIX -definition, which only requires enough space for the input wide -character. - -This does not break much in practice because when users supply buffers -smaller than MB_CUR_MAX (e.g. in ncurses), they compute and dynamically -allocate the buffer, which results in enough spare space (thanks to -usable_size in malloc and padding in alloca) that no actual buffer -overflow occurs. However when the code is built with _FORTIFY_SOURCE, -it runs into the hard check against MB_CUR_MAX in __wcrtomb_chk and -hence fails. It wasn't evident until now since dynamic allocations -would result in wcrtomb not being fortified but since _FORTIFY_SOURCE=3, -that limitation is gone, resulting in such code failing. - -To fix this problem, introduce an internal buffer that is MB_LEN_MAX -long and use that to perform the conversion and then copy the resultant -bytes into the destination buffer. Also move the fortification check -into the main implementation, which checks the result after conversion -and aborts if the resultant byte count is greater than the destination -buffer size. - -One complication is that applications that assume the MB_CUR_MAX -limitation to be gone may not be able to run safely on older glibcs if -they use static destination buffers smaller than MB_CUR_MAX; dynamic -allocations will always have enough spare space that no actual overruns -will occur. One alternative to fixing this is to bump symbol version to -prevent them from running on older glibcs but that seems too strict a -constraint. Instead, since these users will only have made this -decision on reading the manual, I have put a note in the manual warning -them about the pitfalls of having static buffers smaller than -MB_CUR_MAX and running them on older glibc. - -Benchmarking: - -The wcrtomb microbenchmark shows significant increases in maximum -execution time for all locales, ranging from 10x for ar_SA.UTF-8 to -1.5x-2x for nearly everything else. The mean execution time however saw -practically no impact, with some results even being quicker, indicating -that cache locality has a much bigger role in the overhead. - -Given that the additional copy uses a temporary buffer inside wcrtomb, -it's likely that a hot path will end up putting that buffer (which is -responsible for the additional overhead) in a similar place on stack, -giving the necessary cache locality to negate the overhead. However in -situations where wcrtomb ends up getting called at wildly different -spots on the call stack (or is on different call stacks, e.g. with -threads or different execution contexts) and is still a hotspot, the -performance lag will be visible. - -Signed-off-by: Siddhesh Poyarekar ---- - debug/tst-fortify.c | 7 ++++++- - debug/wcrtomb_chk.c | 8 ++------ - include/wchar.h | 4 ++++ - manual/charset.texi | 11 ++++++----- - wcsmbs/wcrtomb.c | 31 +++++++++++++++++++++++-------- - 5 files changed, 41 insertions(+), 20 deletions(-) - -diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c -index 03c9867714..8e94643bf2 100644 ---- a/debug/tst-fortify.c -+++ b/debug/tst-fortify.c -@@ -1478,10 +1478,15 @@ do_test (void) - character which has a multibyte representation which does not - fit. */ - CHK_FAIL_START -- char smallbuf[2]; -+ char smallbuf[1]; - if (wcrtomb (smallbuf, L'\x100', &s) != 2) - FAIL (); - CHK_FAIL_END -+ -+ /* Same input with a large enough buffer and we're good. */ -+ char bigenoughbuf[2]; -+ if (wcrtomb (bigenoughbuf, L'\x100', &s) != 2) -+ FAIL (); - #endif - - wchar_t wenough[10]; -diff --git a/debug/wcrtomb_chk.c b/debug/wcrtomb_chk.c -index 8b6d026560..28c3ea0d2d 100644 ---- a/debug/wcrtomb_chk.c -+++ b/debug/wcrtomb_chk.c -@@ -1,4 +1,5 @@ - /* Copyright (C) 2005-2022 Free Software Foundation, Inc. -+ Copyright The GNU Toolchain Authors. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or -@@ -25,10 +26,5 @@ - size_t - __wcrtomb_chk (char *s, wchar_t wchar, mbstate_t *ps, size_t buflen) - { -- /* We do not have to implement the full wctomb semantics since we -- know that S cannot be NULL when we come here. */ -- if (buflen < MB_CUR_MAX) -- __chk_fail (); -- -- return __wcrtomb (s, wchar, ps); -+ return __wcrtomb_internal (s, wchar, ps, buflen); - } -diff --git a/include/wchar.h b/include/wchar.h -index 4267985625..db83297bca 100644 ---- a/include/wchar.h -+++ b/include/wchar.h -@@ -172,6 +172,10 @@ libc_hidden_proto (__mbrtowc) - libc_hidden_proto (__mbrlen) - extern size_t __wcrtomb (char *__restrict __s, wchar_t __wc, - __mbstate_t *__restrict __ps) attribute_hidden; -+extern size_t __wcrtomb_internal (char *__restrict __s, wchar_t __wc, -+ __mbstate_t *__restrict __ps, -+ size_t __s_size) -+ attribute_hidden; - extern size_t __mbsrtowcs (wchar_t *__restrict __dst, - const char **__restrict __src, - size_t __len, __mbstate_t *__restrict __ps) -diff --git a/manual/charset.texi b/manual/charset.texi -index a9b5cb4a37..427db3bc80 100644 ---- a/manual/charset.texi -+++ b/manual/charset.texi -@@ -883,11 +883,12 @@ the string @var{s}. This includes all bytes representing shift - sequences. - - One word about the interface of the function: there is no parameter --specifying the length of the array @var{s}. Instead the function --assumes that there are at least @code{MB_CUR_MAX} bytes available since --this is the maximum length of any byte sequence representing a single --character. So the caller has to make sure that there is enough space --available, otherwise buffer overruns can occur. -+specifying the length of the array @var{s}, so the caller has to make sure -+that there is enough space available, otherwise buffer overruns can occur. -+This version of @theglibc{} does not assume that @var{s} is at least -+@var{MB_CUR_MAX} bytes long, but programs that need to run on @glibcadj{} -+versions that have this assumption documented in the manual must comply -+with this limit. - - @pindex wchar.h - @code{wcrtomb} was introduced in @w{Amendment 1} to @w{ISO C90} and is -diff --git a/wcsmbs/wcrtomb.c b/wcsmbs/wcrtomb.c -index e17438989f..c0cce3792f 100644 ---- a/wcsmbs/wcrtomb.c -+++ b/wcsmbs/wcrtomb.c -@@ -1,4 +1,5 @@ - /* Copyright (C) 1996-2022 Free Software Foundation, Inc. -+ Copyright The GNU Toolchain Authors. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or -@@ -20,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -34,7 +36,7 @@ - static mbstate_t state; - - size_t --__wcrtomb (char *s, wchar_t wc, mbstate_t *ps) -+__wcrtomb_internal (char *s, wchar_t wc, mbstate_t *ps, size_t s_size) - { - char buf[MB_LEN_MAX]; - struct __gconv_step_data data; -@@ -52,14 +54,11 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps) - /* A first special case is if S is NULL. This means put PS in the - initial state. */ - if (s == NULL) -- { -- s = buf; -- wc = L'\0'; -- } -+ wc = L'\0'; - - /* Tell where we want to have the result. */ -- data.__outbuf = (unsigned char *) s; -- data.__outbufend = (unsigned char *) s + MB_CUR_MAX; -+ data.__outbuf = (unsigned char *) buf; -+ data.__outbufend = (unsigned char *) buf + sizeof buf; - - /* Get the conversion functions. */ - fcts = get_gconv_fcts (_NL_CURRENT_DATA (LC_CTYPE)); -@@ -101,7 +100,17 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps) - - if (status == __GCONV_OK || status == __GCONV_EMPTY_INPUT - || status == __GCONV_FULL_OUTPUT) -- result = data.__outbuf - (unsigned char *) s; -+ { -+ result = data.__outbuf - (unsigned char *) buf; -+ -+ if (s != NULL) -+ { -+ if (result > s_size) -+ __chk_fail (); -+ -+ memcpy (s, buf, result); -+ } -+ } - else - { - result = (size_t) -1; -@@ -110,5 +119,11 @@ __wcrtomb (char *s, wchar_t wc, mbstate_t *ps) - - return result; - } -+ -+size_t -+__wcrtomb (char *s, wchar_t wc, mbstate_t *ps) -+{ -+ return __wcrtomb_internal (s, wc, ps, (size_t) -1); -+} - weak_alias (__wcrtomb, wcrtomb) - libc_hidden_weak (wcrtomb) --- -2.35.3 -