strcat.3, strncat.3: RIP strncat(3)

Message ID 20221205154904.15321-1-alx@kernel.org
State Not applicable
Headers
Series strcat.3, strncat.3: RIP strncat(3) |

Checks

Context Check Description
dj/TryBot-apply_patch fail Patch failed to apply to master at the time it was sent
dj/TryBot-32bit fail Patch series failed to apply

Commit Message

Alejandro Colomar Dec. 5, 2022, 3:49 p.m. UTC
  Never use this function.  Really.

Cc: <pkg-shadow-devel@alioth-lists.debian.net>
Cc: <libc-alpha@sourceware.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
---

Hi!

To shadow-utils readers, I've seen there are a few uses of strncat(3) in
shadow-utils.  I'll review my current PR about string handling to also
address this issue.

To glibc readers, please bury this function deep down as if it were
radioactive waste.

Cheers,

Alex


 man3/strcat.3  | 75 +++-------------------------------------
 man3/strncat.3 | 92 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 95 insertions(+), 72 deletions(-)
  

Comments

Alejandro Colomar Dec. 5, 2022, 3:56 p.m. UTC | #1
On 12/5/22 16:49, Alejandro Colomar wrote:
> Never use this function.  Really.
> 
> Cc: <pkg-shadow-devel@alioth-lists.debian.net>
> Cc: <libc-alpha@sourceware.org>
> Signed-off-by: Alejandro Colomar <alx@kernel.org>
> ---
> 
> Hi!
> 
> To shadow-utils readers, I've seen there are a few uses of strncat(3) in
> shadow-utils.  I'll review my current PR about string handling to also
> address this issue.
> 
> To glibc readers, please bury this function deep down as if it were
> radioactive waste.
> 
> Cheers,
> 
> Alex
> 

The rendered version of the new manual page for strncpy(3) is:


strncat(3)              Library Functions Manual             strncat(3)

NAME
        strncat - concatenate two strings

LIBRARY
        Standard C library (libc, -lc)

SYNOPSIS
        #include <string.h>

        [[deprecated]]
        char *strncat(char dest[restrict strlen(.dest) + strnlen(.n) + 1],
                      const char src[restrict .n],
                      size_t n);

DESCRIPTION
        Note: Never use this function.

        For  safe  string concatenation, see strlcat(3bsd).  For copying
        or concatenating a string into a fixed‐length buffer with  zero‐
        ing of the rest, see stpncpy(3).

        strncat() appends at most n characters of src to the end of dst.
        It  always terminates with a null character the string placed in
        dest.

        A simple implementation of strncat() might be:

            char *
            strncat(char *dest, const char *src, size_t n)
            {
                return memcpy(dest + strlen(dest), src, strnlen(src, n));
            }

RETURN VALUE
        strncat() returns a pointer to the resulting string dest.

ATTRIBUTES
        For an explanation of the terms used in this  section,  see  at‐
        tributes(7).
        ┌─────────────────────────────────────┬───────────────┬─────────┐
        │Interface                            │ Attribute     │ Value   │
        ├─────────────────────────────────────┼───────────────┼─────────┤
        │strncat()                            │ Thread safety │ MT‐Safe │
        └─────────────────────────────────────┴───────────────┴─────────┘

STANDARDS
        POSIX.1‐2001, POSIX.1‐2008, C89, C99, SVr4, 4.3BSD.

BUGS
        All.  Seriously, there’s no use case for this function.

        It  has  a very misleading name.  This function has no relation‐
        ship with strncpy(3).

        Since it doesn’t know the size of the destination  buffer,  this
        function  can  easily  write past the end of the array, being an
        open door to all kinds of crackers.

SEE ALSO
        strcpy(3), string(3)

Linux man‐pages (unreleased)     (date)                      strncat(3)

-- 
<http://www.alejandro-colomar.es/>
  

Patch

diff --git a/man3/strcat.3 b/man3/strcat.3
index 61d3e54f1..277e5b1e4 100644
--- a/man3/strcat.3
+++ b/man3/strcat.3
@@ -11,7 +11,7 @@ 
 .\"     Improve discussion of strncat().
 .TH strcat 3 (date) "Linux man-pages (unreleased)"
 .SH NAME
-strcat, strncat \- concatenate two strings
+strcat \- concatenate two strings
 .SH LIBRARY
 Standard C library
 .RI ( libc ", " \-lc )
@@ -20,8 +20,6 @@  .SH SYNOPSIS
 .B #include <string.h>
 .PP
 .BI "char *strcat(char *restrict " dest ", const char *restrict " src );
-.BI "char *strncat(char " dest "[restrict strlen(." dest ") + strnlen(." n ") + 1],"
-.BI "              const char " src "[restrict ." n "], size_t " n );
 .fi
 .SH DESCRIPTION
 The
@@ -42,73 +40,10 @@  .SH DESCRIPTION
 .I dest
 is not large enough, program behavior is unpredictable;
 .IR "buffer overruns are a favorite avenue for attacking secure programs" .
-.PP
-The
-.BR strncat ()
-function is similar, except that
-.IP \(bu 3
-it will use at most
-.I n
-bytes from
-.IR src ;
-and
-.IP \(bu
-.I src
-does not need to be null-terminated if it contains
-.I n
-or more bytes.
-.PP
-As with
-.BR strcat (),
-the resulting string in
-.I dest
-is always null-terminated.
-.PP
-If
-.I src
-contains
-.I n
-or more bytes,
-.BR strncat ()
-writes
-.I n+1
-bytes to
-.I dest
-.RI ( n
-from
-.I src
-plus the terminating null byte).
-Therefore, the size of
-.I dest
-must be at least
-.IR "strlen(dest)+n+1" .
-.PP
-A simple implementation of
-.BR strncat ()
-might be:
-.PP
-.in +4n
-.EX
-char *
-strncat(char *dest, const char *src, size_t n)
-{
-    size_t dest_len = strlen(dest);
-    size_t i;
-
-    for (i = 0 ; i < n && src[i] != \(aq\e0\(aq ; i++)
-        dest[dest_len + i] = src[i];
-    dest[dest_len + i] = \(aq\e0\(aq;
-
-    return dest;
-}
-.EE
-.in
 .SH RETURN VALUE
 The
 .BR strcat ()
-and
-.BR strncat ()
-functions return a pointer to the resulting string
+function returns a pointer to the resulting string
 .IR dest .
 .SH ATTRIBUTES
 For an explanation of the terms used in this section, see
@@ -175,12 +110,10 @@  .SH NOTES
 .SH EXAMPLES
 Because
 .BR strcat ()
-and
-.BR strncat ()
 must find the null byte that terminates the string
 .I dest
 using a search that starts at the beginning of the string,
-the execution time of these functions
+the execution time of this function
 scales according to the length of the string
 .IR dest .
 This can be demonstrated by running the program below.
@@ -222,6 +155,6 @@  .SH SEE ALSO
 .BR memcpy (3),
 .BR strcpy (3),
 .BR string (3),
-.BR strncpy (3),
+.BR strlcat (3bsd),
 .BR wcscat (3),
 .BR wcsncat (3)
diff --git a/man3/strncat.3 b/man3/strncat.3
index dc3a1ca1c..fefd68c84 100644
--- a/man3/strncat.3
+++ b/man3/strncat.3
@@ -1 +1,91 @@ 
-.so man3/strcat.3
+.\" Copyright 2022 Alejandro Colomar <alx@kernel.org>
+.\"
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
+.\"
+.TH strncat 3 (date) "Linux man-pages (unreleased)"
+.SH NAME
+strncat \- concatenate two strings
+.SH LIBRARY
+Standard C library
+.RI ( libc ", " \-lc )
+.SH SYNOPSIS
+.nf
+.B #include <string.h>
+.PP
+.B [[deprecated]]
+.BI "char *strncat(char " dest "[restrict strlen(." dest ") + strnlen(." n ") + 1],"
+.BI "              const char " src "[restrict ." n ],
+.BI "              size_t " n );
+.fi
+.SH DESCRIPTION
+.BI Note: " Never use this function."
+.PP
+For safe string concatenation, see
+.BR strlcat (3bsd).
+For copying or concatenating a string into a fixed-length buffer
+with zeroing of the rest, see
+.BR stpncpy (3).
+.PP
+.BR strncat ()
+appends at most
+.I n
+characters of
+.I src
+to the end of
+.IR dst .
+It always terminates with a null character the string placed in
+.IR dest .
+.PP
+A simple implementation of
+.BR strncat ()
+might be:
+.PP
+.in +4n
+.EX
+char *
+strncat(char *dest, const char *src, size_t n)
+{
+    return memcpy(dest + strlen(dest), src, strnlen(src, n));
+}
+.EE
+.in
+.SH RETURN VALUE
+.BR strncat ()
+returns a pointer to the resulting string
+.IR dest .
+.SH ATTRIBUTES
+For an explanation of the terms used in this section, see
+.BR attributes (7).
+.ad l
+.nh
+.TS
+allbox;
+lbx lb lb
+l l l.
+Interface	Attribute	Value
+T{
+.BR strncat ()
+T}	Thread safety	MT-Safe
+.TE
+.hy
+.ad
+.sp 1
+.SH STANDARDS
+POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD.
+.SH BUGS
+All.
+Seriously,
+there's no use case for this function.
+.PP
+It has a
+.I very
+misleading name.
+This function has no relationship with
+.BR strncpy (3).
+.PP
+Since it doesn't know the size of the destination buffer,
+this function can easily write past the end of the array,
+being an open door to all kinds of crackers.
+.SH SEE ALSO
+.BR strcpy (3),
+.BR string (3)