From patchwork Tue Nov 24 19:16:38 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 548252 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id D35FB1402C2 for ; Wed, 25 Nov 2015 06:16:53 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b=jR5uOH3F; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:subject:to:references:cc:from:message-id:date :mime-version:in-reply-to:content-type; q=dns; s=default; b=SUx1 g8RHxLHHumOn5licBOG3Ke1IZGH3BQXN7Wh0j8mJTypS/CFKnBc/ZQDttx7QBXQx kF/P6LHuXeH56bfXWZ6ZQTelOFzjc/QZy7FJgba6Bt++MTV/SYLcUTOvo0+w7NUM V1P7l5wfgjEjNVaTHhvnYhvtG1Mp0o20voRodGw= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:subject:to:references:cc:from:message-id:date :mime-version:in-reply-to:content-type; s=default; bh=G9lgIGV3n5 987mLY/NwpZJnzozA=; b=jR5uOH3FtoBnniVMnYh+8aW+m44lKMdJqVNh4eDRkS owLfrordcdjJUILmapiA7ej5WMmzhpC/UJt2bmXdhYRa/KHvtcGYjCHhXkSs9J1/ zICgHEHODGItaTsn1I++mnI91PmSu8uIqYqqZKJBEYrqxQ1le3zy3kd+yRxULWcn 4= Received: (qmail 14112 invoked by alias); 24 Nov 2015 19:16:47 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 14101 invoked by uid 89); 24 Nov 2015 19:16:46 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Subject: Re: [PATCH] Implement strlcat [BZ#178] To: Paul Eggert References: <56547472.3010302@redhat.com> <5654B1FE.5020100@cs.ucla.edu> Cc: GNU C Library From: Florian Weimer Message-ID: <5654B796.7070302@redhat.com> Date: Tue, 24 Nov 2015 20:16:38 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 In-Reply-To: <5654B1FE.5020100@cs.ucla.edu> On 11/24/2015 07:52 PM, Paul Eggert wrote: > First, the proposed change to the manual still suffers from the problems > I mentioned earlier, and the strlcpy patch makes these problems worse. I > would like to help fix this by condensing my scattered > documentation-related comments into a proposed patch. I'm attaching the consolidated documentation patch. > Second, strlcpy and strlcat should both be marked __wur. This would > remove a significant part of my objection to the proposed change, which > is that these poorly-designed APIs encourage silent-truncation bugs. I disagree. We don't do that for snprintf, which is very similar, and we do not check most snprintf results in glibc. Florian diff --git a/manual/string.texi b/manual/string.texi index 5f8a17e..65f50f9 100644 --- a/manual/string.texi +++ b/manual/string.texi @@ -576,17 +576,59 @@ there is no null terminator written into @var{to}. If the length of @var{from} is less than @var{size}, then @code{strncpy} copies all of @var{from}, followed by enough null characters to add up -to @var{size} characters in all. This behavior is rarely useful, but it -is specified by the @w{ISO C} standard. +to @var{size} characters in all. The behavior of @code{strncpy} is undefined if the strings overlap. -Using @code{strncpy} as opposed to @code{strcpy} is a way to avoid bugs +Not guaranteeing null termination and always overwriting the entire +destination buffer makes @code{strncpy} rarely useful, but this behavior +is specified by the @w{ISO C} standard. See @code{strlcpy} below for an +alternative which null-terminates the destination string as long as the +destination buffer does not have length zero. +@end deftypefun + +@comment string.h +@comment BSD +@deftypefun size_t strlcpy (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +This function is similar to @code{strcpy}, but copies at most @var{size} +characters into the destination buffer @var{to}, including the +terminating null character. + +If @var{size} is zero, nothing is written to @var{to}. + +If the length of the string @var{from} is equal to or greater than +@var{size}, @code{strlcpy} copies only the first @samp{@var{size} - 1} +characters to the destination buffer @var{to}, and writes a terminating +null character to the last character in the buffer. + +If the length of @var{from} is less than @var{size}, @code{strlcpy} +copies all of the string @var{from} to the destination buffer @var{to}, +followed by a single null character. Like other string functions such +as @code{strcpy}, but unlike @code{strncpy}, the remaining characters in +the destination buffer, if any, remain unchanged. + +The return value @var{result} of @code{strlcpy} is the length of the +string @var{from}. This means that @samp{@var{result} >= @var{size}} is +true whenever truncation occurs. + +The string @var{from} must be null-terminated even if its length exceeds +that of the destination buffer specified as @var{size}. The behavior of +@code{strlcpy} is undefined if the strings overlap or if the source or +destination are null pointers. + +Using @code{strlcpy} as opposed to @code{strcpy} is a way to avoid bugs relating to writing past the end of the allocated space for @var{to}. -However, it can also make your program much slower in one common case: -copying a string which is probably small into a potentially large buffer. -In this case, @var{size} may be large, and when it is, @code{strncpy} will -waste a considerable amount of time copying null characters. +Unlike @code{strncpy}, @code{strlcpy} ensures that the destination +string is always null-terminated (unless the buffer size is zero), and +it does not fill the remaining part of the buffer with null characters. + +@strong{Note:} GNU programs should not use statically sized buffers for +storing strings. @xref{Semantics, , Writing Robust Programs, standards, +The GNU Coding Standards}. Instead of using @code{strlcpy}, it is +usually better to use dynamic memory allocation (@pxref{Unconstrained +Allocation}) and functions such as @code{strdup} or @code{asprintf} to +construct strings. @end deftypefun @comment wchar.h @@ -1041,6 +1083,38 @@ hello, wo @comment string.h @comment BSD +@deftypefun size_t strlcat (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +This function appends the null-terminated string @var{from} to the +string @var{to}, limiting the total length of the result string at +@var{to} (including the null terminator) to @var{size}. + +If the original string @var{to} contains a null terminator among the +first @var{size} characters, @code{strlcat} copies as much as possible +of the string @var{from} into the buffer at @var{to} of @var{size} +characters, starting at the terminating null character of the original +string @var{to}. In effect, this appends the string @var{from} to the +string @var{to}. In this case, the resulting string in @var{to} will +always be null-terminated, and it is truncated if necessary (not all +characters in @var{from} are copied). @code{strlcat} still returns the +length of the untruncated string, the sum of the original length of +@var{to} and the length of @var{from}. + +If the original string @var{to} is not null-terminated (within the first +@var{size} characters of the buffer), @code{strlcat} returns @var{size} +plus the length of the string @var{from}. In this case, the string +@var{to} is unchanged, and will not be null-terminated. This also +covers the case when @var{size} is zero. + +@strong{Note:} GNU programs should not use statically sized buffers for +storing strings. @xref{Semantics, , Writing Robust Programs, standards, +The GNU Coding Standards}. Instead of using @code{strlcat}, it is +usually better to use dynamic memory allocation (@pxref{Unconstrained +Allocation}) and and the @code{asprintf} function to construct strings. +@end deftypefun + +@comment string.h +@comment BSD @deftypefun void bcopy (const void *@var{from}, void *@var{to}, size_t @var{size}) @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} This is a partially obsolete alternative for @code{memmove}, derived from