Never use this function. Really. Cc: <pkg-shadow-devel@xxxxxxxxxxxxxxxxxxxxxxx> Cc: <libc-alpha@xxxxxxxxxxxxxx> Signed-off-by: Alejandro Colomar <alx@xxxxxxxxxx> --- 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(-) 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@xxxxxxxxxx> +.\" +.\" 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) -- 2.38.1