Cc: Martin Sebor <msebor@xxxxxxxxxx> Cc: "G. Branden Robinson" <g.branden.robinson@xxxxxxxxx> Cc: Douglas McIlroy <douglas.mcilroy@xxxxxxxxxxxxx> Cc: Jakub Wilk <jwilk@xxxxxxxxx> Cc: Serge Hallyn <serge@xxxxxxxxxx> Cc: Iker Pedrosa <ipedrosa@xxxxxxxxxx> Cc: Andrew Pinski <pinskia@xxxxxxxxx> Cc: Stefan Puiu <stefan.puiu@xxxxxxxxx> Signed-off-by: Alejandro Colomar <alx@xxxxxxxxxx> --- man3/strncat.3 | 157 ++++++++++++++++++------------------------------- 1 file changed, 57 insertions(+), 100 deletions(-) diff --git a/man3/strncat.3 b/man3/strncat.3 index 6e4bf6d78..45fe0575c 100644 --- a/man3/strncat.3 +++ b/man3/strncat.3 @@ -1,10 +1,11 @@ +'\" t .\" 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 an unterminated string into a string +strncat \- concatenate a null-padded character sequence into a string .SH LIBRARY Standard C library .RI ( libc ", " \-lc ) @@ -12,54 +13,41 @@ .SH SYNOPSIS .nf .B #include <string.h> .PP -.BI "char *strncat(char " dest "[restrict strlen(." dest ") + ." n " + 1]," -.BI " const char " src "[restrict ." n ], -.BI " size_t " n ); +.BI "char *strncat(char *restrict " dst ", const char " src "[restrict ." sz ], +.BI " size_t " sz ); .fi .SH DESCRIPTION -.IR Note : -This is probably not the function you want to use. -For string concatenation with truncation, 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 +This function catenates the input character sequence +contained in a null-padded fixed-width buffer, +into a string at the buffer pointed to by .IR dst . -It always terminates with a null character the string placed in -.IR dest . +The programmer is responsible for allocating a destination buffer large enough, +that is, +.IR "strlen(dst) + strnlen(src, sz) + 1" . .PP -An implementation of -.BR strncat () -might be: +An implementation of this function might be: .PP .in +4n .EX char * -strncat(char *dest, const char *src, size_t n) +strncat(char *restrict dst, const char *restrict src, size_t sz) { - char *cat; - size_t len; + int len; + char *p; - cat = dest + strlen(dest); - len = strnlen(src, n); - memcpy(cat, src, len); - cat[len] = \(aq\e0\(aq; + len = strnlen(src, sz); + p = dst + strlen(dst); + p = mempcpy(p, src, len); + *p = \(aq\e0\(aq; - return dest; + return dst; } .EE .in .SH RETURN VALUE .BR strncat () -returns a pointer to the resulting string -.IR dest . +returns +.IR dst . .SH ATTRIBUTES For an explanation of the terms used in this section, see .BR attributes (7). @@ -79,65 +67,25 @@ .SH ATTRIBUTES .sp 1 .SH STANDARDS POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD. -.SH NOTES -.SS ustr2stpe() -You may want to write your own function similar to -.BR strncpy (), -with the following improvements: -.IP \(bu 3 -Copy, instead of concatenating. -There's no equivalent of -.BR strncat () -that copies instead of concatenating. -.IP \(bu -Allow chaining the function, -by returning a suitable pointer. -Copy chaining is faster than concatenating. -.IP \(bu -Don't check for null characters in the middle of the unterminated string. -If the string is terminated, this function should not be used. -If the string is unterminated, it is unnecessary. -.IP \(bu -A name that tells what it does: -Copy from an -.IR u nterminated -.IR str ing -to a -.IR st ring, -and return a -.IR p ointer -to its end. -.PP -.in +4n -.EX -/* This code is in the public domain. - * - * char *ustr2stp(char dst[restrict .n+1], - * const char src[restrict .n], - * size_t len); - */ -char * -ustr2stp(char *restrict dst, const char *restrict src, size_t len) -{ - memcpy(dst, src, len); - dst[len] = \(aq\e0\(aq; - - return dst + len; -} -.EE -.in .SH CAVEATS -This function doesn't know the size of the destination buffer, -so it can overrun the buffer if the programmer wasn't careful enough. -.SH BUGS -.BR strncat (3) -has a misleading name; -it has no relationship with +The name of this function is confusing. +This function has no relation to .BR strncpy (3). +.PP +If the destination buffer is not large enough, +the behavior is undefined. +See +.B _FORTIFY_SOURCE +in +.BR feature_test_macros (7). +.SH BUGS +This function can be very inefficient. +Read about +.UR https://www.joelonsoftware.com/\:2001/12/11/\:back\-to\-basics/ +Shlemiel the painter +.UE . .SH EXAMPLES -The following program creates a string -from a concatenation of unterminated strings. -.\" SRC BEGIN (strncpy.c) +.\" SRC BEGIN (strncat.c) .EX #include <stdio.h> #include <stdlib.h> @@ -148,24 +96,33 @@ .SH EXAMPLES int main(void) { - char pre[4] = "pre."; - char *post = ".post"; - char *src = "some_long_body.post"; - char dest[100]; + size_t maxsize; - dest[0] = \(aq\e0\(aq; + // Null-padded fixed-width character sequences + char pre[4] = "pre."; + char new_post[50] = ".foo.bar"; + + // Strings + char post[] = ".post"; + char src[] = "some_long_body.post"; + char *dest; + + maxsize = nitems(pre) + strlen(src) \- strlen(post) + + nitems(new_post) + 1; + dest = malloc(sizeof(*dest) * maxsize); + + dest[0] = \(aq\e0\(aq; // There's no 'cpy' function to this 'cat'. strncat(dest, pre, nitems(pre)); strncat(dest, src, strlen(src) \- strlen(post)); + strncat(dest, new_post, nitems(new_post)); - puts(dest); // "pre.some_long_body" + puts(dest); // "pre.some_long_body.foo.bar" + free(dest); exit(EXIT_SUCCESS); } .EE .\" SRC END .in .SH SEE ALSO -.BR memccpy (3), -.BR memcpy (3), -.BR mempcpy (3), -.BR strcpy (3), -.BR string (3) +.BR string (3), +.BR string_copy (3) -- 2.39.0