From patchwork Sun Nov 12 11:26:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Colomar X-Patchwork-Id: 79637 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 560FE385841B for ; Sun, 12 Nov 2023 11:27:21 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by sourceware.org (Postfix) with ESMTPS id A4F8F3858D37 for ; Sun, 12 Nov 2023 11:26:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A4F8F3858D37 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=kernel.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A4F8F3858D37 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=145.40.73.55 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699788415; cv=none; b=iKLZrbqzqQW5jW0Anydb6wh0vrv+Z1PMmK6m9al7ge+v5pVWu9OK5soqHieSurCfL4ZD/tyXOwRv5bJT73NIY/ykz5+++RbHz5UZRne8p2sNSDlOYZffXqO+JhAsUppaT95MiOcSYTrkQ+cd4wn7gy2AdwStV2iCz+lVh87ZtPA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699788415; c=relaxed/simple; bh=NvsLuhuzUB/V8+oiw9HqjyEG6qGrqTx6Grd0CLznoAk=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=cXeW9+u6+TStWPOD0/ISEEcn3E6kEGpaGy/mwoWsrWeK5ZKRQuFMmw7mZMehjaPPk7XX81eMdmpoVVn3k8nrHQ+lCaCmaFJ2TJAoTHclRSzEk5BWTQ6Qoohb2TYJQj6AnOQ2TfFyx/CUW/cHBpIrE6DT24BzLLqb7SiCzjrQROM= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sin.source.kernel.org (Postfix) with ESMTP id 49794CE0C70; Sun, 12 Nov 2023 11:26:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4ED8EC433C8; Sun, 12 Nov 2023 11:26:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1699788409; bh=NvsLuhuzUB/V8+oiw9HqjyEG6qGrqTx6Grd0CLznoAk=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=akTIHwTZChgXg2/JaCZ5nQz6pmbRpta9hyYmD3IP3w7yVmZ+PSWKqKZ6dfRGci6uV 3QY5lEDDBUgW0uo3GZhXHrHirwkPrE/MKu29LFMP+p34MiW3LdublA5OTXTPdti81e doHZ3tkOJVAMdfCz8XSmVy83VbFO44HYb2ptmycWrzDb+46ZMKH7hQFcPmY7pnw71k FnBygAYU3vV5pr1tG3JGRf5yRu2ZcxpuzDY7PiM3XDybEBzHnJ8Tb7f8mGR/7N4U5D h8de410Tzlbq28z+xv/IKKod/AdG5NlW8O6oyx4aeyogBXlYP1tu3AfHTdKK0gjqi3 c2QsSWx1ls+NA== Date: Sun, 12 Nov 2023 12:26:44 +0100 From: Alejandro Colomar To: linux-man@vger.kernel.org Cc: Alejandro Colomar , libc-alpha@sourceware.org, Guillem Jover , Paul Eggert , Jonny Grant , DJ Delorie , Matthew House , Oskari Pirhonen , Thorsten Kukuk , Adhemerval Zanella Netto , Zack Weinberg , "G. Branden Robinson" , Carlos O'Donell , Xi Ruoyao , Stefan Puiu , Andreas Schwab Subject: [PATCH v2 1/3] string_copying.7: BUGS: *cat(3) functions aren't always bad Message-ID: <20231112112629.13827-3-alx@kernel.org> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Mailer: git-send-email 2.42.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, 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 X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org The compiler will sometimes optimize them to normal *cpy(3) functions, since the length of dst is usually known, if the previous *cpy(3) is visible to the compiler. And they provide for cleaner code. If you know that they'll get optimized, you could use them. Cc: Paul Eggert Cc: Jonny Grant Cc: DJ Delorie Cc: Matthew House Cc: Oskari Pirhonen Cc: Thorsten Kukuk Cc: Adhemerval Zanella Netto Cc: Zack Weinberg Cc: "G. Branden Robinson" Cc: Carlos O'Donell Cc: Xi Ruoyao Cc: Stefan Puiu Cc: Andreas Schwab Signed-off-by: Alejandro Colomar --- man7/string_copying.7 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/man7/string_copying.7 b/man7/string_copying.7 index 1637ebc91..0254fbba6 100644 --- a/man7/string_copying.7 +++ b/man7/string_copying.7 @@ -592,8 +592,14 @@ .SH BUGS All catenation functions share the same performance problem: .UR https://www.joelonsoftware.com/\:2001/12/11/\:back\-to\-basics/ Shlemiel the painter .UE . +As a mitigation, +compilers are able to transform some calls to catenation functions +into normal copy functions, +since +.I strlen(dst) +is usually a byproduct of the previous copy. .\" ----- EXAMPLES :: -------------------------------------------------/ .SH EXAMPLES The following are examples of correct use of each of these functions. .\" ----- EXAMPLES :: stpcpy(3) ---------------------------------------/ From patchwork Sun Nov 12 11:26:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Colomar X-Patchwork-Id: 79636 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9ED603858298 for ; Sun, 12 Nov 2023 11:27:11 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by sourceware.org (Postfix) with ESMTPS id C15A43858C29 for ; Sun, 12 Nov 2023 11:26:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C15A43858C29 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=kernel.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C15A43858C29 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=145.40.68.75 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699788418; cv=none; b=RR6XmZDfQEUQE+eY2bmZFQTjHBAW9jZ1VBSymth0ngvARW1lEcnMbvvEhtU+NPEWocFeWQSkn58CUIKy5/AE8AYb8mltGrfPovhZ0W0WeCbBscX1QJ4kVOZ4FCYKUkXLl7jewspLHuQYhqLfoGhIezypAYB5563WokW29vRK8x0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699788418; c=relaxed/simple; bh=yVi+lj8581Tb4erLHGRME+3JfFenz0cB6Qb5TPUiCpc=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=YljODtD029ZVmivP9lwf/enSA8AuNbhByhIc3FRgL8W6SDqoEHtMgH42LsPJp7pjaSFM2TwndAAnDf6d9A819quTcVtk4QSb5ikkdymKh2XfmVsdJCeDlo+Q5BjRFK9b8FfnjQaPSc80WifFjf6N7W2tHgj0A2Wt344rzoJAgVc= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by ams.source.kernel.org (Postfix) with ESMTP id 6FA42B8077C; Sun, 12 Nov 2023 11:26:55 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9969BC433C8; Sun, 12 Nov 2023 11:26:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1699788414; bh=yVi+lj8581Tb4erLHGRME+3JfFenz0cB6Qb5TPUiCpc=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=XHL3h+b/m4vxZFM0PzK5C12Sa114RT5x09m5zVtsjJdhX6pZHfGr+GW3GNd7ug2sx L8Ku93y00nC3UkczrQRd1IAz2Yf+Ip/5TQ3pLNzRIWbz+b/dHQUiZgrhI38IM8l1Fe qcQeYxL1sSG0/3y1D461VirnOkZk1x0HMITxKb2WUYqcmynUK9lF4KAAiK2gwWRere P748DHiIkvAk0PNaE3d31k67OqFC2kwovuZduwBlRA7kiei4KxdvTr5twDhIKAi5TD RZyN+EBtSM7qaTA2K3g0CvORV28//K/M4DY2NKQlBIXLwlzJWcG5+ffXrBJb36zotk uo2mg4MCT76rQ== Date: Sun, 12 Nov 2023 12:26:49 +0100 From: Alejandro Colomar To: linux-man@vger.kernel.org Cc: Alejandro Colomar , libc-alpha@sourceware.org, Guillem Jover , Paul Eggert , Jonny Grant , DJ Delorie , Matthew House , Oskari Pirhonen , Thorsten Kukuk , Adhemerval Zanella Netto , Zack Weinberg , "G. Branden Robinson" , Carlos O'Donell , Xi Ruoyao , Stefan Puiu , Andreas Schwab Subject: [PATCH v2 2/3] string_copying.7: BUGS: Document strl{cpy,cat}(3)'s performance problems Message-ID: <20231112112629.13827-4-alx@kernel.org> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Mailer: git-send-email 2.42.0 X-Spam-Status: No, score=-9.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, 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 X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Also point to BUGS from other sections that talk about these functions. These functions are doomed due to the design decision of mirroring snprintf(3)'s return value. They must return strlen(src), which makes them terribly slow, and vulnerable to DoS if an attacker can control strlen(src). A better design would have been to return -1 when truncating. Reported-by: Paul Eggert Cc: Jonny Grant Cc: DJ Delorie Cc: Matthew House Cc: Oskari Pirhonen Cc: Thorsten Kukuk Cc: Adhemerval Zanella Netto Cc: Zack Weinberg Cc: "G. Branden Robinson" Cc: Carlos O'Donell Cc: Xi Ruoyao Cc: Stefan Puiu Cc: Andreas Schwab Cc: Guillem Jover Signed-off-by: Alejandro Colomar --- man7/string_copying.7 | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/man7/string_copying.7 b/man7/string_copying.7 index 0254fbba6..cb3910db0 100644 --- a/man7/string_copying.7 +++ b/man7/string_copying.7 @@ -226,9 +226,9 @@ .SS Truncate or not? .IP \[bu] .BR strlcpy (3bsd) and .BR strlcat (3bsd) -are similar, but less efficient when chained. +are similar, but have important performance problems; see BUGS. .IP \[bu] .BR stpncpy (3) and .BR strncpy (3) @@ -417,8 +417,10 @@ .SS Functions the resulting string is truncated (but it is guaranteed to be null-terminated). They return the length of the total string they tried to create. .IP +Check BUGS before using these functions. +.IP .BR stpecpy (3) is a simpler alternative to these functions. .\" ----- DESCRIPTION :: Functions :: stpncpy(3) ----------------------/ .TP @@ -598,8 +600,22 @@ .SH BUGS into normal copy functions, since .I strlen(dst) is usually a byproduct of the previous copy. +.P +.BR strlcpy (3) +and +.BR strlcat (3) +need to read the entire +.I src +string, +even if the destination buffer is small. +This makes them vulnerable to Denial of Service (DoS) attacks +if an attacker can control the length of the +.I src +string. +And if not, +they're still unnecessarily slow. .\" ----- EXAMPLES :: -------------------------------------------------/ .SH EXAMPLES The following are examples of correct use of each of these functions. .\" ----- EXAMPLES :: stpcpy(3) ---------------------------------------/ From patchwork Sun Nov 12 11:27:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Colomar X-Patchwork-Id: 79638 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C59633858404 for ; Sun, 12 Nov 2023 11:27:56 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by sourceware.org (Postfix) with ESMTPS id 340B43858D20 for ; Sun, 12 Nov 2023 11:27:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 340B43858D20 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=kernel.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=kernel.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 340B43858D20 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2604:1380:4601:e00::1 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699788465; cv=none; b=emb6X4KV5kW30sNV3UvkCsHXz2yfP2j88SEfkv3o2RN2SXkTACYg2zHF/S0OqpDatqBvajON54AWUhpGuQKxyjpLD+U+3pPZN1xIEM7xsbSHAOcVvdR3omPYyGz5NvvoVvM/MpxdrffCmocIR3k+/6ORjvSxRr27bCRf4n3rccs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699788465; c=relaxed/simple; bh=RMNaYx+Yae4fxJj1Bmypd8wPEPlNeui7IxL4fTlNJJ4=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=velublBLR6QEwjnx+LE6zerD8mlsZXjIhi/LhBiTMhVI3meUzFHrMoyZ7sE+u5GVGA8TfFwurGeh0SPdH8G3t6HNBnl2DSwqUxjE+UdeL+o37YL4DvD9pGIqrK/GGcPJU7WAdrvPMTpCPprt09k6r6unTo357l40yCCtcCisKO8= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by ams.source.kernel.org (Postfix) with ESMTP id 45617B8077C; Sun, 12 Nov 2023 11:27:41 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 67198C433C7; Sun, 12 Nov 2023 11:27:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1699788460; bh=RMNaYx+Yae4fxJj1Bmypd8wPEPlNeui7IxL4fTlNJJ4=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=M5XSAsoKUikQJ9QNdLm4dopLNNMrL+7f7mxP9v4tRO6ylurq5ZTR7G0N8hOKdXbPP 1km7Xjl89yiE/uKG9ds9du2EmqJyngKva+97WP/Q2r4KJWUC6pnp96JCgUw1xaxm8M hmDghAi1l2EZO9gP1nnMv/5rjOHMMp+5kCmjjqliSvo+wFDuBDSmttgfqLxqR4nM98 /4RxOsDlDrmb/x2YhiXaDlSj7ACzVrdIrim+b400k+0s+YdH8BuzeFmrxIRl/znj/q 2qra7i+uoOKMqpuIOj1wO8KQRTCwrBMq/UtkTC0X/9UYuz2Ii830s1JQbYg+H98f5k 55NB7JwxM10WQ== Date: Sun, 12 Nov 2023 12:27:35 +0100 From: Alejandro Colomar To: linux-man@vger.kernel.org Cc: Alejandro Colomar , libc-alpha@sourceware.org, Guillem Jover , Paul Eggert , Jonny Grant , DJ Delorie , Matthew House , Oskari Pirhonen , Thorsten Kukuk , Adhemerval Zanella Netto , Zack Weinberg , "G. Branden Robinson" , Carlos O'Donell , Xi Ruoyao , Stefan Puiu , Andreas Schwab Subject: [PATCH v2 3/3] strtcpy.3, string_copying.7: Add strtcpy(3) Message-ID: <20231112112732.14002-1-alx@kernel.org> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Mailer: git-send-email 2.42.0 X-Spam-Status: No, score=-9.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, 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 X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Add this new truncating string-copying function. It intends to fully replace strlcpy(3), which has important bugs (documented in the preceeding commit). It is almost identical to Linux kernel's strscpy(9), so reduce the documentation of strscpy(9) in this page to the minimum, giving preference to strtcpy(3). Provide a reference implementation, since no libc provides it. Providing an easy, safe, and relatively fast truncating string-copying function should prevent users from rolling their own, in which they might introduce bugs accidentally. We already made enough mistakes while discussing these functions, so it's certainly not something that should be written often. Cc: Paul Eggert Cc: Jonny Grant Cc: DJ Delorie Cc: Matthew House Cc: Oskari Pirhonen Cc: Thorsten Kukuk Cc: Adhemerval Zanella Netto Cc: Zack Weinberg Cc: "G. Branden Robinson" Cc: Carlos O'Donell Cc: Xi Ruoyao Cc: Stefan Puiu Cc: Andreas Schwab Cc: Guillem Jover Signed-off-by: Alejandro Colomar --- man3/strtcpy.3 | 1 + man7/string_copying.7 | 97 ++++++++++++++++++++++++++++++------------- 2 files changed, 69 insertions(+), 29 deletions(-) create mode 100644 man3/strtcpy.3 diff --git a/man3/strtcpy.3 b/man3/strtcpy.3 new file mode 100644 index 000000000..beb850746 --- /dev/null +++ b/man3/strtcpy.3 @@ -0,0 +1 @@ +.so man7/string_copying.7 diff --git a/man7/string_copying.7 b/man7/string_copying.7 index cb3910db0..4f609e480 100644 --- a/man7/string_copying.7 +++ b/man7/string_copying.7 @@ -6,8 +6,9 @@ .\" ----- NAME :: -----------------------------------------------------/ .SH NAME stpcpy, strcpy, strcat, +strtcpy, stpecpy, strlcpy, strlcat, stpncpy, strncpy, @@ -30,8 +31,11 @@ .SS Strings // Chain-copy a string with truncation. .BI "char *stpecpy(char *" dst ", char " end "[0], const char *restrict " src ); .P // Copy/catenate a string with truncation. +.BI "size_t strtcpy(char " dst "[restrict ." sz "], \ +const char *restrict " src , +.BI " size_t " sz ); .BI "size_t strlcpy(char " dst "[restrict ." sz "], \ const char *restrict " src , .BI " size_t " sz ); .BI "size_t strlcat(char " dst "[restrict ." sz "], \ @@ -220,10 +224,10 @@ .SS Truncate or not? .P Functions that truncate: .IP \[bu] 3 .BR stpecpy (3) -is the most efficient string copy function that performs truncation. -It only requires to check for truncation once after all chained calls. +.IP \[bu] +.BR strtcpy (3) .IP \[bu] .BR strlcpy (3bsd) and .BR strlcat (3bsd) @@ -326,8 +330,10 @@ .SS String vs character sequence .IP \[bu] .BR strcpy (3), .BR strcat (3) .IP \[bu] +.BR strtcpy (3) +.IP \[bu] .BR stpecpy (3) .IP \[bu] .BR strlcpy (3bsd), .BR strlcat (3bsd) @@ -390,12 +396,24 @@ .SS Functions The return value is useless. .IP .BR stpcpy (3) is a faster alternative to these functions. +.\" ----- DESCRIPTION :: Functions :: strtcpy(3) ----------------------/ +.TP +.BR strtcpy (3) +Copy the input string into a destination string. +If the destination buffer isn't large enough to hold the copy, +the resulting string is truncated +(but it is guaranteed to be null-terminated). +It returns the length of the string, +or \-1 if it truncated. +.IP +This function is not provided by any library; +see EXAMPLES for a reference implementation. .\" ----- DESCRIPTION :: Functions :: stpecpy(3) ----------------------/ .TP .BR stpecpy (3) -Copy the input string into a destination string. +Chain-copy the input string into a destination string. If the destination buffer, limited by a pointer to its end, isn't large enough to hold the copy, the resulting string is truncated @@ -419,10 +437,12 @@ .SS Functions They return the length of the total string they tried to create. .IP Check BUGS before using these functions. .IP +.BR strtcpy (3) +and .BR stpecpy (3) -is a simpler alternative to these functions. +are better alternatives to these functions. .\" ----- DESCRIPTION :: Functions :: stpncpy(3) ----------------------/ .TP .BR stpncpy (3) Copy the input string into @@ -542,8 +562,17 @@ .SH RETURN VALUE .BR ustpcpy (3) A pointer to one after the last character in the destination character sequence. .TP +.BR strtcpy (3) +The length of the string. +When truncation occurs, it returns \-1. +When +.I dsize +is +.BR 0 , +it also returns \-1. +.TP .BR strlcpy (3bsd) .TQ .BR strlcat (3bsd) The length of the total string that they tried to create @@ -562,25 +591,14 @@ .SH RETURN VALUE which is useless. .\" ----- NOTES :: strscpy(9) -----------------------------------------/ .SH NOTES The Linux kernel has an internal function for copying strings, -which is similar to -.BR stpecpy (3), -except that it can't be chained: -.TP -.BR strscpy (9) -Copy the input string into a destination string. -If the destination buffer, -limited by its size, -isn't large enough to hold the copy, -the resulting string is truncated -(but it is guaranteed to be null-terminated). -It returns the length of the destination string, or +.BR strscpy (9), +which is identical to +.BR strtcpy (3), +except that it returns .B \-E2BIG -on truncation. -.IP -.BR stpecpy (3) -is a simpler and faster alternative to this function. +instead of \-1. .\" ----- CAVEATS :: --------------------------------------------------/ .SH CAVEATS Don't mix chain calls to truncating and non-truncating functions. It is conceptually wrong @@ -640,8 +658,17 @@ .SH EXAMPLES strcat(buf, "!"); len = strlen(buf); puts(buf); .EE +.\" ----- EXAMPLES :: strtcpy(3) --------------------------------------/ +.TP +.BR strtcpy (3) +.EX +len = strtcpy(buf, "Hello world!", sizeof(buf)); +if (len == \-1) + goto toolong; +puts(buf); +.EE .\" ----- EXAMPLES :: stpecpy(3) --------------------------------------/ .TP .BR stpecpy (3) .EX @@ -671,17 +698,8 @@ .SH EXAMPLES if (len >= sizeof(buf)) goto toolong; puts(buf); .EE -.\" ----- EXAMPLES :: strscpy(9) --------------------------------------/ -.TP -.BR strscpy (9) -.EX -len = strscpy(buf, "Hello world!", sizeof(buf)); -if (len == \-E2BIG) - goto toolong; -puts(buf); -.EE .\" ----- EXAMPLES :: stpncpy(3) --------------------------------------/ .TP .BR stpncpy (3) .EX @@ -765,8 +783,29 @@ .SS Implementations .in +4n .EX /* This code is in the public domain. */ \& +.\" ----- EXAMPLES :: Implementations :: strtcpy(3) -------------------/ +ssize_t +.IR strtcpy "(char *restrict dst, const char *restrict src, size_t sz)" +{ + bool trunc; + char *p; + size_t dlen, slen; +\& + if (dsize == 0) + return \-1; +\& + slen = strnlen(src, dsize); + trunc = (slen == dsize); + dlen = slen \- trunc; +\& + p = mempcpy(dst, src, dlen); + *p = \[aq]\e0\[aq]; + + return trunc ? \-1 : slen; +} +\& .\" ----- EXAMPLES :: Implementations :: stpecpy(3) -------------------/ char * .IR stpecpy "(char *dst, char end[0], const char *restrict src)" {