Implement strlcat [BZ#178]

Message ID 5669AE8D.3000705@cs.ucla.edu
State New, archived
Headers

Commit Message

Paul Eggert Dec. 10, 2015, 4:55 p.m. UTC
  On 12/04/2015 12:20 PM, Paul Eggert wrote:
> Or perhaps you'd rather not document _FORTIFY_SOURCE at all? I notice 
> it's mentioned nowhere in the manual; is that intended? If so, I can 
> further revise accordingly. 

No further comment, so I played it safe and removed mention of 
_FORTIFY_SOURCE before installing the cleanup patch to the 
string-function documentation. While I was at it I added a reference to 
GCC's new -fcheck-pointer-bounds option and a cross-reference to the GCC 
manual. These just-installed doc changes are independent of whether 
strlcpy+strlcat should be added. Although I still hope we don't add 
strlcpy+strlcat, a proposed doc patch for it is attached in case we do.
  

Patch

From a6b08708e2f098b459d49c9f6b9121e3d5320301 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Thu, 10 Dec 2015 08:18:10 -0800
Subject: [PATCH] Add strlcpy, strlcat

[BZ #178]
This patch was derived from text by Florian Weimer in:
https://sourceware.org/ml/libc-alpha/2015-11/msg00558.html
* manual/string.texi (Truncating Strings): New functions from BSD.
---
 ChangeLog          |   6 ++++
 manual/string.texi | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index 81e5791..b93fd8d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@ 
 2015-12-10  Paul Eggert  <eggert@cs.ucla.edu>
 
+	Add strlcpy, strlcat
+	[BZ #178]
+	This patch was derived from text by Florian Weimer in:
+	https://sourceware.org/ml/libc-alpha/2015-11/msg00558.html
+	* manual/string.texi (Truncating Strings): New functions from BSD.
+
 	Split large string section; add truncation advice
 	* manual/examples/strncat.c: Remove.
 	This example was misleading, as the code would have undefined
diff --git a/manual/string.texi b/manual/string.texi
index 016fd0b..33f5732 100644
--- a/manual/string.texi
+++ b/manual/string.texi
@@ -745,7 +745,7 @@  As noted below, this function has significant performance issues.
 @end deftypefun
 
 Programmers using the @code{strcat} or @code{wcscat} function (or the
-@code{strncat} or @code{wcsncat} functions defined in
+@code{strlcat}, @code{strncat}, or @code{wcsncat} functions defined in
 a later section, for that matter)
 can easily be recognized as lazy and reckless.  In almost all situations
 the lengths of the participating strings are known (it better should be
@@ -906,6 +906,47 @@  greater than the length of @var{from}.  As noted below, this function
 is generally a poor choice for processing text.
 @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} bytes from the string @var{from} into the destination
+buffer @var{to}, including a terminating null byte.
+
+If @var{size} is greater than the length of @var{from}, this function
+copies all of the string @var{from} to the destination buffer
+@var{to}, including the terminating null byte.  Like other string
+functions such as @code{strcpy}, but unlike @code{strncpy}, any
+remaining bytes in the destination buffer remain unchanged.
+
+If @var{size} is nonzero and is not greater than the length of the
+string @var{from}, this function copies only the first
+@samp{@var{size} - 1} bytes to the destination buffer @var{to}, and
+writes a terminating null byte to the last byte in the buffer.
+
+This function returns the length of @var{from}.  This means that
+truncation occurs whenever the returned value is not less than
+@var{size}.
+
+The behavior of this function is undefined if @var{size} is zero, if
+the source and destination strings overlap, or if the source or
+destination are null pointers.
+
+Unlike @code{strncpy}, this function always null-terminates the
+destination string, does not zero-fill the destination buffer,
+requires @var{size} to be nonzero, requires @var{from} to be a
+null-terminated string, and always computes @var{from}'s length even
+when greater than @var{size}.
+
+This function was designed as a stopgap for quickly retrofitting
+possibly-unsafe uses of @code{strcpy} on platforms lacking
+buffer-overrun protection.  As noted below, this function is generally
+a poor choice for processing text.
+
+This function is derived from BSD.
+@end deftypefun
+
 @comment wchar.h
 @comment ISO
 @deftypefun {wchar_t *} wcsncpy (wchar_t *restrict @var{wto}, const wchar_t *restrict @var{wfrom}, size_t @var{size})
@@ -1065,6 +1106,65 @@  choice for processing text.  Also, this function has significant
 performance issues.  @xref{Concatenating Strings}.
 @end deftypefun
 
+@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 is similar to @code{strcat}, except that it truncates
+@var{to} to at most @var{size} bytes (including the terminating null
+byte) when appending the string @var{from} to the string @var{to}.
+
+This function appends a prefix of the string @var{from} to the string
+@var{to}.  The prefix contains all of @var{from} if that can be
+appended to @var{to} without requiring more than @var{size} bytes
+total, including the null terminator.  Otherwise, it contains only as
+many leading bytes of @var{from} as will fit.  The resulting string in
+@var{to} is always null-terminated, and any excess trailing bytes of
+@var{from} are not copied.
+
+This function returns the sum of the original length of @var{to} and
+the length of @var{from}.  This means that truncation occurs whenever
+the returned value is not less than @var{size}.
+
+The behavior is undefined if @var{to} does not contain a null byte in
+its first @var{size} bytes, if the source and resulting destination
+strings overlap, if the source or destination are null pointers, or if
+the result would exceed @code{SIZE_MAX}.
+
+@strong{Portability Note:} With @theglibc{} this function's behavior
+is never undefined due to the result exceeding @code{SIZE_MAX}, as
+@var{from} and @var{to} cannot overlap and @theglibc{} assumes a flat
+address space.
+
+This function could be implemented like this:
+
+@smallexample
+@group
+size_t
+strlcat (char *to, const char *from, size_t size)
+@{
+  size_t len = strlen (to);
+  return len + strlcpy (to + len, from, size - len);
+@}
+@end group
+@end smallexample
+
+Whereas @code{strncat} limits the length of the appended string, this
+function limits the total destination size.  Also, unlike
+@code{strncat}, this function requires @var{from} to be
+null-terminated and always computes @var{from}'s length even when
+greater than the limit.
+
+As a companion to @code{strlcpy}, this function was designed as a
+stopgap for quickly retrofitting possibly-unsafe uses of @code{strcat}
+on platforms lacking buffer-overrun protection.  As noted below, this
+function is generally a poor choice for processing text.  Also, like
+@code{strcat} this function has significant performance issues.
+@xref{Concatenating Strings}.
+
+This function is derived from BSD.
+@end deftypefun
+
 @comment wchar.h
 @comment ISO
 @deftypefun {wchar_t *} wcsncat (wchar_t *restrict @var{wto}, const wchar_t *restrict @var{wfrom}, size_t @var{size})
-- 
2.1.0