From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from eastern.birch.relay.mailchannels.net (eastern.birch.relay.mailchannels.net [23.83.209.55]) by sourceware.org (Postfix) with ESMTPS id E76ED3858416 for ; Tue, 6 Jun 2023 05:56:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E76ED3858416 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gotplt.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gotplt.org X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id 3469582106B; Tue, 6 Jun 2023 05:56:05 +0000 (UTC) Received: from pdx1-sub0-mail-a283.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id BF610821062; Tue, 6 Jun 2023 05:56:04 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1686030964; a=rsa-sha256; cv=none; b=sLVZuRx+L3LdELv/3aczRGoJAMjIXhQSnkWZxTwk+cg2EWUvInqKpcymoqLCeWWvpByQlf yS2rwCORaeN9eotLIKBqucX/XLOWtsFf/+xK56wwFc8SDFWZ0fHugrwiX3mNnZVIsGE7uY U+dFEnwzRu5SFruIOECFXSHb1syX2h/s9tsq2Rx7oKlQWMfn3EuPafNeQlESZ3p2cRT0t3 iV8AfeJJLJBwB3PzNUiGaR/naqyLLiUNzbYnS9LvLJqvVSW3MZ959byIPlV0fK3oI1tr6Q BxslBr/7n2g8pLDNjpU7LqKAXm65f3QyzROLHAKjUcMgMZURSgCpdsKhbJsTdA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1686030964; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=gKI2/LqoWrQrmmkPjsl5ESO+ZE0a6EM07GaRJ0JxzMI=; b=SnVcEV2jlPIQswvNi34PcKAW9tyjhfX6eQazZNwkL7A2+6KldMShiNQgnrDO3U3sJIcONH hO3jU2KTJp/HEv+O6rTZl/YkaPQbbnnjlia5qUUddvjY1zDSzd1ttJlj1zdJE8yCAf9nqW bKVbncQ4ejJIBoJ+wvGLcMUaoApbIpYf87Y5gR6RDAcs8XLa76Ukh7tUoyfM1ac+PCKsjE zpcrwI1CJPpi5LNnyICH9luAu+ywMQM6n1v4M4fTGYL34CS3OS6WCrtLKOqJA9GWH5M+mh xDxhz1NqonmvN7VibBQyIrmoQ1sEOOAIKyjyntQbVfWITHW4uYvt2/7X8DsMRA== ARC-Authentication-Results: i=1; rspamd-5f966895c-q2dzp; auth=pass smtp.auth=dreamhost smtp.mailfrom=siddhesh@gotplt.org X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|siddhesh@gotplt.org X-MailChannels-Auth-Id: dreamhost X-Abortive-Desert: 2ef3340a58f7cc81_1686030965081_2351115947 X-MC-Loop-Signature: 1686030965081:4064754890 X-MC-Ingress-Time: 1686030965081 Received: from pdx1-sub0-mail-a283.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.104.253.241 (trex/6.8.1); Tue, 06 Jun 2023 05:56:05 +0000 Received: from [192.168.0.182] (bras-vprn-toroon4834w-lp130-02-142-113-138-85.dsl.bell.ca [142.113.138.85]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) (Authenticated sender: siddhesh@gotplt.org) by pdx1-sub0-mail-a283.dreamhost.com (Postfix) with ESMTPSA id 4Qb08N1BY9zC3; Mon, 5 Jun 2023 22:56:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gotplt.org; s=dreamhost; t=1686030964; bh=gKI2/LqoWrQrmmkPjsl5ESO+ZE0a6EM07GaRJ0JxzMI=; h=Date:Subject:To:From:Content-Type:Content-Transfer-Encoding; b=VKoao5s7jkIdkvVYS2NVrjucPwoO2Du53GEdJbqhek/fCW2+9/45Xr22kumecx8IA H8COp2RJXpRs0fiU5kJ/3/mWJ+TxsBwLujErOdN8QhrtWmTFVHp0wA8Q8H7qOi41l8 jwOKNyw7z8R+PTEHOCILptL8h1DrVkkHUNKaUrap33oVo6QfqEnCOaB1iG7wvct70M jv/Oo+cfBOjfhQus/UdXnPDcpp+p5wodpHO+/p87VyH1M4OuuNGkRF0mzm0PcFw8pT 1d6gRJnaiRyNT5eeQP4FvTQzYd5LsN34CFl3IPosrfn9fVsjW8EA04zofdzDUfaCYQ jjJ1AJhyFmNWA== Message-ID: <0f2c50f3-e55a-1282-2fec-33b667e1702f@gotplt.org> Date: Tue, 6 Jun 2023 01:56:02 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.10.0 Subject: Re: [PATCH v2 2/3] Add the wcslcpy, wcslcat functions Content-Language: en-US To: Florian Weimer , libc-alpha@sourceware.org References: From: Siddhesh Poyarekar In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-3037.4 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 2023-04-20 08:28, Florian Weimer via Libc-alpha wrote: > These functions are about to be added to POSIX, under Austin Group > issue 986. > > The fortified versions use byte counters instead of character counts > for the compiler-generated size argument. This is expected to result > in less generated code for dynamic object sizes because most allocation > functions use byte counts, not wide character counts. Does it really matter? You'd be scaling in the _chk function instead of outside, so there doesn't really seem anything worthwhile to gain. Not to mention that it's a constant, power of 2 scaling, which any CPU worth its salt should just breeze through. I feel like it'll become a wee bit harder to talk about these functions years later where we'd be like "the fortified variants of the wide char functions take in the size of the destination in number of wchars, except wcslcat and wcslcpy, which take in number of bytes", not to mention situations where we forget that wcslcat and wcslcpy are different. The rest looks OK. > --- > debug/Makefile | 2 + > debug/Versions | 2 + > debug/tst-fortify.c | 17 ++++ > debug/wcslcat_chk.c | 31 +++++++ > debug/wcslcpy_chk.c | 31 +++++++ > include/wchar.h | 5 + > sysdeps/mach/hurd/i386/libc.abilist | 4 + > sysdeps/unix/sysv/linux/aarch64/libc.abilist | 4 + > sysdeps/unix/sysv/linux/alpha/libc.abilist | 4 + > sysdeps/unix/sysv/linux/arc/libc.abilist | 4 + > sysdeps/unix/sysv/linux/arm/be/libc.abilist | 4 + > sysdeps/unix/sysv/linux/arm/le/libc.abilist | 4 + > sysdeps/unix/sysv/linux/csky/libc.abilist | 4 + > sysdeps/unix/sysv/linux/hppa/libc.abilist | 4 + > sysdeps/unix/sysv/linux/i386/libc.abilist | 4 + > sysdeps/unix/sysv/linux/ia64/libc.abilist | 4 + > .../sysv/linux/loongarch/lp64/libc.abilist | 4 + > .../sysv/linux/m68k/coldfire/libc.abilist | 4 + > .../unix/sysv/linux/m68k/m680x0/libc.abilist | 4 + > .../sysv/linux/microblaze/be/libc.abilist | 4 + > .../sysv/linux/microblaze/le/libc.abilist | 4 + > .../sysv/linux/mips/mips32/fpu/libc.abilist | 4 + > .../sysv/linux/mips/mips32/nofpu/libc.abilist | 4 + > .../sysv/linux/mips/mips64/n32/libc.abilist | 4 + > .../sysv/linux/mips/mips64/n64/libc.abilist | 4 + > sysdeps/unix/sysv/linux/nios2/libc.abilist | 4 + > sysdeps/unix/sysv/linux/or1k/libc.abilist | 4 + > .../linux/powerpc/powerpc32/fpu/libc.abilist | 4 + > .../powerpc/powerpc32/nofpu/libc.abilist | 4 + > .../linux/powerpc/powerpc64/be/libc.abilist | 4 + > .../linux/powerpc/powerpc64/le/libc.abilist | 4 + > .../unix/sysv/linux/riscv/rv32/libc.abilist | 4 + > .../unix/sysv/linux/riscv/rv64/libc.abilist | 4 + > .../unix/sysv/linux/s390/s390-32/libc.abilist | 4 + > .../unix/sysv/linux/s390/s390-64/libc.abilist | 4 + > sysdeps/unix/sysv/linux/sh/be/libc.abilist | 4 + > sysdeps/unix/sysv/linux/sh/le/libc.abilist | 4 + > .../sysv/linux/sparc/sparc32/libc.abilist | 4 + > .../sysv/linux/sparc/sparc64/libc.abilist | 4 + > .../unix/sysv/linux/x86_64/64/libc.abilist | 4 + > .../unix/sysv/linux/x86_64/x32/libc.abilist | 4 + > wcsmbs/Makefile | 4 + > wcsmbs/Versions | 2 + > wcsmbs/bits/wchar2.h | 37 ++++++++ > wcsmbs/tst-wcslcat.c | 93 +++++++++++++++++++ > wcsmbs/tst-wcslcpy.c | 78 ++++++++++++++++ > wcsmbs/wchar.h | 13 +++ > wcsmbs/wcslcat.c | 60 ++++++++++++ > wcsmbs/wcslcpy.c | 46 +++++++++ > 49 files changed, 561 insertions(+) > create mode 100644 debug/wcslcat_chk.c > create mode 100644 debug/wcslcpy_chk.c > create mode 100644 wcsmbs/tst-wcslcat.c > create mode 100644 wcsmbs/tst-wcslcpy.c > create mode 100644 wcsmbs/wcslcat.c > create mode 100644 wcsmbs/wcslcpy.c > > diff --git a/debug/Makefile b/debug/Makefile > index f5f27f793c..4f018abecf 100644 > --- a/debug/Makefile > +++ b/debug/Makefile > @@ -104,6 +104,8 @@ routines = \ > wcrtomb_chk \ > wcscat_chk \ > wcscpy_chk \ > + wcslcat_chk \ > + wcslcpy_chk \ > wcsncat_chk \ > wcsncpy_chk \ > wcsnrtombs_chk \ > diff --git a/debug/Versions b/debug/Versions > index 94dfa5f428..9cf2725992 100644 > --- a/debug/Versions > +++ b/debug/Versions > @@ -61,6 +61,8 @@ libc { > GLIBC_2.38 { > __strlcat_chk; > __strlcpy_chk; > + __wcslcat_chk; > + __wcslcpy_chk; > } > GLIBC_PRIVATE { > __fortify_fail; OK. > diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c > index f74a5e04dc..9fe20627ee 100644 > --- a/debug/tst-fortify.c > +++ b/debug/tst-fortify.c > @@ -782,6 +782,18 @@ do_test (void) > wcsncpy (wbuf + 9, L"XABCDEFGH", 8); > CHK_FAIL_END > > + CHK_FAIL_START > + wcslcpy (wbuf + 7, L"X", 4); > + CHK_FAIL_END > + > + CHK_FAIL_START > + wcslcpy (wbuf + 7, L"X", l0 + 4); > + CHK_FAIL_END > + > + CHK_FAIL_START > + wcslcpy (wbuf + 9, L"XABCDEFGH", 8); > + CHK_FAIL_END > + > CHK_FAIL_START > wcpncpy (wbuf + 9, L"XABCDEFGH", 8); > CHK_FAIL_END > @@ -804,6 +816,11 @@ do_test (void) > wcsncat (wbuf, L"ZYXWV", l0 + 3); > CHK_FAIL_END > > + wmemcpy (wbuf, wstr1 + 4, 7); > + CHK_FAIL_START > + wcslcat (wbuf, L"ZYXWV", l0 + 11); > + CHK_FAIL_END > + > CHK_FAIL_START > wmemcpy (wa.buf1 + 1, L"abcdefghij", 10); > CHK_FAIL_END OK. > diff --git a/debug/wcslcat_chk.c b/debug/wcslcat_chk.c > new file mode 100644 > index 0000000000..5d63fba076 > --- /dev/null > +++ b/debug/wcslcat_chk.c > @@ -0,0 +1,31 @@ > +/* Fortified version of wcslcat. > + Copyright (C) 2023 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 > + > +/* Check that the user-supplied size does not exceed the > + compiler-determined size, and then forward to wcslcat. */ > +size_t > +__wcslcat_chk (wchar_t *__restrict s1, const wchar_t *__restrict s2, > + size_t n, size_t s1len) > +{ > + if (__glibc_unlikely (s1len / sizeof (wchar_t) < n)) > + __chk_fail (); > + > + return __wcslcat (s1, s2, n); > +} > diff --git a/debug/wcslcpy_chk.c b/debug/wcslcpy_chk.c > new file mode 100644 > index 0000000000..ff7434b59a > --- /dev/null > +++ b/debug/wcslcpy_chk.c > @@ -0,0 +1,31 @@ > +/* Fortified version of wcslcpy. > + Copyright (C) 2023 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 > + > +/* Check that the user-supplied size does not exceed the > + compiler-determined size, and then forward to wcslcpy. */ > +size_t > +__wcslcpy_chk (wchar_t *__restrict s1, const wchar_t *__restrict s2, > + size_t n, size_t s1len) > +{ > + if (__glibc_unlikely (s1len / sizeof (wchar_t) < n)) > + __chk_fail (); > + > + return __wcslcpy (s1, s2, n); > +} > diff --git a/include/wchar.h b/include/wchar.h > index fafe7c8e9b..ff4ae52045 100644 > --- a/include/wchar.h > +++ b/include/wchar.h > @@ -203,6 +203,8 @@ extern size_t __wcslen (const wchar_t *__s) __attribute_pure__; > extern size_t __wcsnlen (const wchar_t *__s, size_t __maxlen) > __attribute_pure__; > extern wchar_t *__wcscat (wchar_t *dest, const wchar_t *src); > +extern __typeof (wcslcat) __wcslcat; > +libc_hidden_proto (__wcslcat) > extern wint_t __btowc (int __c) attribute_hidden; > extern int __mbsinit (const __mbstate_t *__ps); > extern size_t __mbrtowc (wchar_t *__restrict __pwc, > @@ -237,8 +239,11 @@ extern wchar_t *__wcscpy (wchar_t *__restrict __dest, > const wchar_t *__restrict __src) > attribute_hidden __nonnull ((1, 2)); > libc_hidden_proto (__wcscpy) > +extern __typeof (wcslcpy) __wcslcpy; > +libc_hidden_proto (__wcslcpy) > extern wchar_t *__wcsncpy (wchar_t *__restrict __dest, > const wchar_t *__restrict __src, size_t __n); > + > extern wchar_t *__wcpcpy (wchar_t *__dest, const wchar_t *__src); > extern wchar_t *__wcpncpy (wchar_t *__dest, const wchar_t *__src, > size_t __n); > diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist > index 9b4c5f4719..74a9f427b2 100644 > --- a/sysdeps/mach/hurd/i386/libc.abilist > +++ b/sysdeps/mach/hurd/i386/libc.abilist > @@ -2328,8 +2328,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist > index cf51b88932..c49363e70e 100644 > --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist > @@ -2667,5 +2667,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist > index 4b25f343b8..d6b1dcaae6 100644 > --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist > +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist > @@ -2776,8 +2776,12 @@ GLIBC_2.38 __nldbl___isoc23_vwscanf F > GLIBC_2.38 __nldbl___isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/arc/libc.abilist b/sysdeps/unix/sysv/linux/arc/libc.abilist > index 5a58cc0477..dfe0c3f7b6 100644 > --- a/sysdeps/unix/sysv/linux/arc/libc.abilist > +++ b/sysdeps/unix/sysv/linux/arc/libc.abilist > @@ -2428,5 +2428,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/arm/be/libc.abilist b/sysdeps/unix/sysv/linux/arm/be/libc.abilist > index 99ce948c5c..6c75e5aa76 100644 > --- a/sysdeps/unix/sysv/linux/arm/be/libc.abilist > +++ b/sysdeps/unix/sysv/linux/arm/be/libc.abilist > @@ -548,8 +548,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 > GLIBC_2.4 _IO_2_1_stdin_ D 0xa0 > diff --git a/sysdeps/unix/sysv/linux/arm/le/libc.abilist b/sysdeps/unix/sysv/linux/arm/le/libc.abilist > index c00bf72ebc..03d6f7ae2d 100644 > --- a/sysdeps/unix/sysv/linux/arm/le/libc.abilist > +++ b/sysdeps/unix/sysv/linux/arm/le/libc.abilist > @@ -545,8 +545,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 > GLIBC_2.4 _IO_2_1_stdin_ D 0xa0 > diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist > index 71130f2c6b..d858c108c6 100644 > --- a/sysdeps/unix/sysv/linux/csky/libc.abilist > +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist > @@ -2704,5 +2704,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist > index 5a651c03df..82a14f8ace 100644 > --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist > +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist > @@ -2653,8 +2653,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist > index 12b91ef632..1950b15d5d 100644 > --- a/sysdeps/unix/sysv/linux/i386/libc.abilist > +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist > @@ -2837,8 +2837,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist > index f223c5e08d..d0b9cb279b 100644 > --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist > @@ -2602,8 +2602,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist > index b91ed6e704..e760a631dd 100644 > --- a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist > @@ -2188,5 +2188,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > index 0d91d7f1ae..35785a3d5f 100644 > --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > @@ -549,8 +549,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0x98 > GLIBC_2.4 _IO_2_1_stdin_ D 0x98 > diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > index e87b22747a..4ab2426e0a 100644 > --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > @@ -2780,8 +2780,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist > index f7623d6d72..38faa16232 100644 > --- a/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist > +++ b/sysdeps/unix/sysv/linux/microblaze/be/libc.abilist > @@ -2753,5 +2753,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist > index 298aa99b42..374d658988 100644 > --- a/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist > +++ b/sysdeps/unix/sysv/linux/microblaze/le/libc.abilist > @@ -2750,5 +2750,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > index f83bdc50cd..fcc5e88e91 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > @@ -2745,8 +2745,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > index 611ece2ac4..01eb96cd93 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > @@ -2743,8 +2743,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > index 0af286fda1..a2748b7b74 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > @@ -2751,8 +2751,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > index 8285f2196e..0ae7ba499d 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > @@ -2653,8 +2653,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist > index c7144d7cd8..947495a0e2 100644 > --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist > +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist > @@ -2792,5 +2792,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/or1k/libc.abilist b/sysdeps/unix/sysv/linux/or1k/libc.abilist > index bb43247795..115f1039e7 100644 > --- a/sysdeps/unix/sysv/linux/or1k/libc.abilist > +++ b/sysdeps/unix/sysv/linux/or1k/libc.abilist > @@ -2174,5 +2174,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > index 7cc5660830..19c4c325b0 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > @@ -2819,8 +2819,12 @@ GLIBC_2.38 __nldbl___isoc23_vwscanf F > GLIBC_2.38 __nldbl___isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > index dd290af782..3e043c4044 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > @@ -2852,8 +2852,12 @@ GLIBC_2.38 __nldbl___isoc23_vwscanf F > GLIBC_2.38 __nldbl___isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > index f2b001402c..e4f3a766bb 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist > @@ -2573,8 +2573,12 @@ GLIBC_2.38 __nldbl___isoc23_vwscanf F > GLIBC_2.38 __nldbl___isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > index 9cc431666e..dafe1c4a59 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist > @@ -2887,5 +2887,9 @@ GLIBC_2.38 __nldbl___isoc23_vwscanf F > GLIBC_2.38 __nldbl___isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist > index b9b725f913..b9740a1afc 100644 > --- a/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/riscv/rv32/libc.abilist > @@ -2430,5 +2430,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > index e0f4863856..e3b4656aa2 100644 > --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist > @@ -2630,5 +2630,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > index 8db68fcea7..84cb7a50ed 100644 > --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > @@ -2817,8 +2817,12 @@ GLIBC_2.38 __nldbl___isoc23_vwscanf F > GLIBC_2.38 __nldbl___isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > index ec9747b7ea..33df3b1646 100644 > --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > @@ -2610,8 +2610,12 @@ GLIBC_2.38 __nldbl___isoc23_vwscanf F > GLIBC_2.38 __nldbl___isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/sh/be/libc.abilist b/sysdeps/unix/sysv/linux/sh/be/libc.abilist > index 9576b818d8..94cbccd715 100644 > --- a/sysdeps/unix/sysv/linux/sh/be/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sh/be/libc.abilist > @@ -2660,8 +2660,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/sh/le/libc.abilist b/sysdeps/unix/sysv/linux/sh/le/libc.abilist > index b67b1b2bb5..3bb316a787 100644 > --- a/sysdeps/unix/sysv/linux/sh/le/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sh/le/libc.abilist > @@ -2657,8 +2657,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > index b251fc9c69..6341b491b4 100644 > --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > @@ -2812,8 +2812,12 @@ GLIBC_2.38 __nldbl___isoc23_vwscanf F > GLIBC_2.38 __nldbl___isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 _IO_fprintf F > GLIBC_2.4 _IO_printf F > GLIBC_2.4 _IO_sprintf F > diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > index 5ef9bbec34..8ed1ea2926 100644 > --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > @@ -2625,8 +2625,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > index 9ad800b62e..57cfcc2086 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > @@ -2576,8 +2576,12 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > GLIBC_2.4 __confstr_chk F > GLIBC_2.4 __fgets_chk F > GLIBC_2.4 __fgets_unlocked_chk F > diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > index 6a3a66c5d4..3f0a9f6d82 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > @@ -2682,5 +2682,9 @@ GLIBC_2.38 __isoc23_wcstoumax F > GLIBC_2.38 __isoc23_wscanf F > GLIBC_2.38 __strlcat_chk F > GLIBC_2.38 __strlcpy_chk F > +GLIBC_2.38 __wcslcat_chk F > +GLIBC_2.38 __wcslcpy_chk F > GLIBC_2.38 strlcat F > GLIBC_2.38 strlcpy F > +GLIBC_2.38 wcslcat F > +GLIBC_2.38 wcslcpy F > diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile > index 4aa43252d7..ac03437661 100644 > --- a/wcsmbs/Makefile > +++ b/wcsmbs/Makefile > @@ -66,6 +66,8 @@ routines := \ > wcscpy \ > wcscspn \ > wcsdup \ > + wcslcat \ > + wcslcpy \ > wcslen \ > wcsmbsload \ > wcsncase \ > @@ -146,6 +148,8 @@ tests := \ > tst-wchar-h \ > tst-wcpncpy \ > tst-wcrtomb \ > + tst-wcslcat \ > + tst-wcslcpy \ > tst-wcsnlen \ > tst-wcstod-nan-locale \ > tst-wcstod-nan-sign \ > diff --git a/wcsmbs/Versions b/wcsmbs/Versions > index 2d9391348a..7bdfe43b4a 100644 > --- a/wcsmbs/Versions > +++ b/wcsmbs/Versions > @@ -65,5 +65,7 @@ libc { > __isoc23_vswscanf; > __isoc23_vwscanf; > __isoc23_wscanf; > + wcslcat; > + wcslcpy; > } > } > diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h > index 8b41e6fbd6..02f44ab373 100644 > --- a/wcsmbs/bits/wchar2.h > +++ b/wcsmbs/bits/wchar2.h > @@ -199,6 +199,43 @@ __NTH (wcsncat (wchar_t *__restrict __dest, const wchar_t *__restrict __src, > return __wcsncat_alias (__dest, __src, __n); > } > > +#ifdef __USE_MISC > +extern size_t __wcslcpy_chk (wchar_t *__dest, const wchar_t *__src, size_t __n, > + size_t __destlen) __THROW; > +extern size_t __REDIRECT_NTH (__wcslcpy_alias, > + (wchar_t *__dest, const wchar_t *__src, > + size_t __n), wcslcpy); > + > +__fortify_function size_t > +__NTH (wcslcpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src, > + size_t __n)) > +{ > + if (__glibc_objsize (__dest) != (size_t) -1 > + && (!__builtin_constant_p (__n > + > __glibc_objsize (__dest) / sizeof (wchar_t)) > + || __n > __glibc_objsize (__dest) / sizeof (wchar_t))) > + return __wcslcpy_chk (__dest, __src, __n, __glibc_objsize (__dest)); > + return __wcslcpy_alias (__dest, __src, __n); > +} > + > +extern size_t __wcslcat_chk (wchar_t *__dest, const wchar_t *__src, size_t __n, > + size_t __destlen) __THROW; > +extern size_t __REDIRECT_NTH (__wcslcat_alias, > + (wchar_t *__dest, const wchar_t *__src, > + size_t __n), wcslcat); > + > +__fortify_function size_t > +__NTH (wcslcat (wchar_t *__restrict __dest, const wchar_t *__restrict __src, > + size_t __n)) > +{ > + if (__glibc_objsize (__dest) != (size_t) -1 > + && (!__builtin_constant_p (__n > __glibc_objsize (__dest) > + / sizeof (wchar_t)) > + || __n > __glibc_objsize (__dest) / sizeof (wchar_t))) > + return __wcslcat_chk (__dest, __src, __n, __glibc_objsize (__dest)); > + return __wcslcat_alias (__dest, __src, __n); > +} > +#endif /* __USE_MISC */ > > > extern int __REDIRECT_NTH_LDBL (__swprintf_alias, > diff --git a/wcsmbs/tst-wcslcat.c b/wcsmbs/tst-wcslcat.c > new file mode 100644 > index 0000000000..63c3a164b5 > --- /dev/null > +++ b/wcsmbs/tst-wcslcat.c > @@ -0,0 +1,93 @@ > +/* Test the wcslcat function. > + Copyright (C) 2023 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 int > +do_test (void) > +{ > + struct { > + wchar_t buf1[16]; > + wchar_t buf2[16]; > + } s; > + > + /* Nothing is written to the destination if its size is 0. */ > + wmemset (s.buf1, '@', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + TEST_COMPARE (wcslcat (s.buf1, L"", 0), 0); > + TEST_COMPARE_BLOB (&s, sizeof (s), L"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + TEST_COMPARE (wcslcat (s.buf1, L"Hello!", 0), 6); > + TEST_COMPARE_BLOB (&s, sizeof (s), L"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + > + /* No bytes are are modified in the target buffer if the source > + string is short enough. */ > + wmemset (s.buf1, '@', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + wcscpy (s.buf1, L"He"); > + TEST_COMPARE (wcslcat (s.buf1, L"llo!", array_length (s.buf1)), 6); > + TEST_COMPARE_BLOB (&s, sizeof (s), L"Hello!\0@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + > + /* A source string which fits exactly into the destination buffer is > + not truncated. */ > + wmemset (s.buf1, '@', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + wcscpy (s.buf1, L"H"); > + TEST_COMPARE (wcslcat (s.buf1, L"ello, world!!!", array_length (s.buf1)), > + 15); > + TEST_COMPARE_BLOB (&s, sizeof (s), > + L"Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + > + /* A source string one character longer than the destination buffer > + is truncated by one character. The total length is returned. */ > + wmemset (s.buf1, '@', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + wcscpy (s.buf1, L"Hello"); > + TEST_COMPARE (wcslcat (s.buf1, L", world!!!!", array_length (s.buf1)), 16); > + TEST_COMPARE_BLOB (&s, sizeof (s), > + L"Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + > + /* An even longer source string is truncated as well, and the total > + length is returned. */ > + wmemset (s.buf1, '@', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + wcscpy (s.buf1, L"Hello,"); > + TEST_COMPARE (wcslcat (s.buf1, L" world!!!!!!!!", array_length (s.buf1)), > + 20); > + TEST_COMPARE_BLOB (&s, sizeof (s), > + L"Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + > + /* A destination string which is not NUL-terminated does not result > + in any changes to the buffer. */ > + wmemset (s.buf1, '$', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + TEST_COMPARE (wcslcat (s.buf1, L"", array_length (s.buf1)), 16); > + TEST_COMPARE_BLOB (&s, sizeof (s), L"$$$$$$$$$$$$$$$$@@@@@@@@@@@@@@@@", 128); > + TEST_COMPARE (wcslcat (s.buf1, L"Hello!", array_length (s.buf1)), 22); > + TEST_COMPARE_BLOB (&s, sizeof (s), L"$$$$$$$$$$$$$$$$@@@@@@@@@@@@@@@@", 128); > + TEST_COMPARE (wcslcat (s.buf1, L"Hello, world!!!!!!!!", > + array_length (s.buf1)), 36); > + TEST_COMPARE_BLOB (&s, sizeof (s), L"$$$$$$$$$$$$$$$$@@@@@@@@@@@@@@@@", 128); > + > + return 0; > +} > + > +#include > diff --git a/wcsmbs/tst-wcslcpy.c b/wcsmbs/tst-wcslcpy.c > new file mode 100644 > index 0000000000..8eaffbf0c4 > --- /dev/null > +++ b/wcsmbs/tst-wcslcpy.c > @@ -0,0 +1,78 @@ > +/* Test the wcslcpy function. > + Copyright (C) 2023 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 int > +do_test (void) > +{ > + struct { > + wchar_t buf1[16]; > + wchar_t buf2[16]; > + } s; > + > + /* Nothing is written to the destination if its size is 0. */ > + wmemset (s.buf1, '@', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + TEST_COMPARE (wcslcpy (s.buf1, L"Hello!", 0), 6); > + TEST_COMPARE_BLOB (&s, sizeof (s), L"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + > + /* No bytes are are modified in the target buffer if the source > + string is short enough. */ > + wmemset (s.buf1, '@', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + TEST_COMPARE (wcslcpy (s.buf1, L"Hello!", array_length (s.buf1)), 6); > + TEST_COMPARE_BLOB (&s, sizeof (s), > + L"Hello!\0@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + > + /* A source string which fits exactly into the destination buffer is > + not truncated. */ > + wmemset (s.buf1, '@', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + TEST_COMPARE (wcslcpy (s.buf1, L"Hello, world!!!", array_length (s.buf1)), > + 15); > + TEST_COMPARE_BLOB (&s, sizeof (s), > + L"Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + > + /* A source string one character longer than the destination buffer > + is truncated by one character. The untruncated source length is > + returned. */ > + wmemset (s.buf1, '@', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + TEST_COMPARE (wcslcpy (s.buf1, L"Hello, world!!!!", array_length (s.buf1)), > + 16); > + TEST_COMPARE_BLOB (&s, sizeof (s), > + L"Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + > + /* An even longer source string is truncated as well, and the > + original length is returned. */ > + wmemset (s.buf1, '@', array_length (s.buf1)); > + wmemset (s.buf2, '@', array_length (s.buf2)); > + TEST_COMPARE (wcslcpy (s.buf1, L"Hello, world!!!!!!!!", > + array_length (s.buf1)), 20); > + TEST_COMPARE_BLOB (&s, sizeof (s), > + L"Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", 128); > + > + return 0; > +} > + > +#include > diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h > index acc2eb9ddf..6d15503830 100644 > --- a/wcsmbs/wchar.h > +++ b/wcsmbs/wchar.h > @@ -93,6 +93,19 @@ extern wchar_t *wcsncpy (wchar_t *__restrict __dest, > const wchar_t *__restrict __src, size_t __n) > __THROW __nonnull ((1, 2)); > > +#ifdef __USE_MISC > +/* Copy at most N - 1 characters from SRC to DEST. */ > +extern size_t wcslcpy (wchar_t *__restrict __dest, > + const wchar_t *__restrict __src, size_t __n) > + __THROW __nonnull ((1, 2)) __attr_access ((__write_only__, 1, 3)); > + > +/* Append SRC to DEST, possibly with truncation to keep the total size > + below N. */ > +extern size_t wcslcat (wchar_t *__restrict __dest, > + const wchar_t *__restrict __src, size_t __n) > + __THROW __nonnull ((1, 2)) __attr_access ((__read_write__, 1, 3)); > +#endif > + > /* Append SRC onto DEST. */ > extern wchar_t *wcscat (wchar_t *__restrict __dest, > const wchar_t *__restrict __src) > diff --git a/wcsmbs/wcslcat.c b/wcsmbs/wcslcat.c > new file mode 100644 > index 0000000000..3bac6a2aa0 > --- /dev/null > +++ b/wcsmbs/wcslcat.c > @@ -0,0 +1,60 @@ > +/* Append a null-terminated wide string to another, with length checking. > + Copyright (C) 2023 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 > + > +size_t > +__wcslcat (wchar_t *__restrict dest, const wchar_t *__restrict src, > + size_t size) > +{ > + size_t src_length = __wcslen (src); > + > + /* Our implementation strlcat supports dest == NULL if size == 0 > + (for consistency with snprintf and strlcpy), but wcsnlen does > + not, so we have to cover this case explicitly. */ > + if (size == 0) > + return src_length; > + > + size_t dest_length = __wcsnlen (dest, size); > + if (dest_length != size) > + { > + /* Copy at most the remaining number of characters in the > + destination buffer. Leave for the null terminator. */ > + size_t to_copy = size - dest_length - 1; > + /* But not more than what is available in the source string. */ > + if (to_copy > src_length) > + to_copy = src_length; > + > + wchar_t *target = dest + dest_length; > + __wmemcpy (target, src, to_copy); > + target[to_copy] = '\0'; > + } > + > + /* If the sum wraps around, we have more than SIZE_MAX + 2 bytes in > + the two input strings (including both null terminators). If each > + byte in the address space can be assigned a unique size_t value > + (which the static_assert checks), then by the pigeonhole > + principle, the two input strings must overlap, which is > + undefined. */ > + _Static_assert (sizeof (uintptr_t) == sizeof (size_t), > + "theoretical maximum object size covers address space"); > + return dest_length + src_length; > +} > +libc_hidden_def (__wcslcat) > +weak_alias (__wcslcat, wcslcat) > diff --git a/wcsmbs/wcslcpy.c b/wcsmbs/wcslcpy.c > new file mode 100644 > index 0000000000..a1b1f1b43f > --- /dev/null > +++ b/wcsmbs/wcslcpy.c > @@ -0,0 +1,46 @@ > +/* Copy a null-terminated wide string to a fixed-size buffer. > + Copyright (C) 2023 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 > + > +size_t > +__wcslcpy (wchar_t *__restrict dest, const wchar_t *__restrict src, size_t size) > +{ > + size_t src_length = __wcslen (src); > + > + if (__glibc_unlikely (src_length >= size)) > + { > + if (size > 0) > + { > + /* Copy the leading portion of the string. The last > + character is subsequently overwritten with the null > + terminator, but the destination size is usually a > + multiple of a small power of two, so writing it twice > + should be more efficient than copying an odd number of > + character. */ > + __wmemcpy (dest, src, size); > + dest[size - 1] = '\0'; > + } > + } > + else > + /* Copy the string and its terminating null character. */ > + __wmemcpy (dest, src, src_length + 1); > + return src_length; > +} > +libc_hidden_def (__wcslcpy) > +weak_alias (__wcslcpy, wcslcpy)