[PATCH 3/4] strncat.3 fixes

Paul Eggert
2023-11-12T23:52:31Z

Don't say "concatenate". Use "byte" instead of "character",
and use standalone terminology rather than relying on the
reader already having read string_copying(7).
Don't say "width" when "size" was intended.
Fix indenting of prototype.
Simplify possible implementation, fixing a bug when the
source string length and sz exceed INT_MAX.
Say that strncat is rarely useful.
Say that behavior is undefined if the destination is not a string.
Simplify example by using plain sizeof rather than an nitems macro,
by removing a confusingly-named 'maxsize' local,
and by removing an unnecessary call to 'exit'.
---
man3/strncat.3 | 54 +++++++++++++++++++++-----------------------------
1 file changed, 23 insertions(+), 31 deletions(-)

diff --git a/man3/strncat.3 b/man3/strncat.3
index d0f777d36..9a7df474a 100644
--- a/man3/strncat.3
+++ b/man3/strncat.3
@@ -5,7 +5,8 @@
.\"
.TH strncat 3 (date) "Linux man-pages (unreleased)"
.SH NAME
-strncat \- concatenate a null-padded character sequence into a string
+strncat \- append non-null bytes from a source array to a string,
+and null-terminate the result
.SH LIBRARY
Standard C library
.RI ( libc ", " \-lc )
@@ -14,15 +15,18 @@ Standard C library
.B #include <string.h>
.P
.BI "char *strncat(char *restrict " dst ", const char " src "[restrict ." sz ],
-.BI " size_t " sz );
+.BI " size_t " sz );
.fi
.SH DESCRIPTION
-This function catenates the input character sequence
-contained in a null-padded fixed-width buffer,
-into a string at the buffer pointed to by
+This function appends at most
+.I sz
+non-null bytes from the array pointed to by
+.I src
+to the end of the string pointed to by
.IR dst .
-The programmer is responsible for allocating a destination buffer large enough,
-that is,
+.I dst
+must point to a string contained in a buffer that is large enough,
+that is, the buffer size must be at least
.IR "strlen(dst) + strnlen(src, sz) + 1" .
.P
An implementation of this function might be:
@@ -32,12 +36,7 @@ An implementation of this function might be:
char *
strncat(char *restrict dst, const char *restrict src, size_t sz)
{
- int len;
- char *p;
-\&
- len = strnlen(src, sz);
- p = dst + strlen(dst);
- p = mempcpy(p, src, len);
+ char *p = mempcpy(dst + strlen(dst), src, strnlen(src, sz));
*p = \[aq]\e0\[aq];
\&
return dst;
@@ -67,11 +66,12 @@ C11, POSIX.1-2008.
.SH HISTORY
POSIX.1-2001, C89, SVr4, 4.3BSD.
.SH CAVEATS
-The name of this function is confusing.
-This function has no relation to
+The name of this function is confusing, as it has no relation to
.BR strncpy (3).
+This function is rarely useful in practice.
.P
-If the destination buffer is not large enough,
+If the destination buffer does not already contain a string,
+or is not large enough,
the behavior is undefined.
See
.B _FORTIFY_SOURCE
@@ -91,40 +91,32 @@ Shlemiel the painter
#include <stdlib.h>
#include <string.h>
\&
-#define nitems(arr) (sizeof((arr)) / sizeof((arr)[0]))
-\&
int
main(void)
{
- size_t maxsize;
-\&
- // Null-padded fixed-width character sequences
+ // Null-padded fixed-size 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);
+ char *dest = malloc(sizeof pre + strlen(src) \- strlen(post)
+ + sizeof new_post + 1);
if (dest == NULL)
err(EXIT_FAILURE, "malloc()");
\&
- dest[0] = \[aq]\e0\[aq]; // There's no 'cpy' function to this 'cat'.
- strncat(dest, pre, nitems(pre));
+ dest[0] = \[aq]\e0\[aq]; // There's no `cpy' function to this `cat'.
+ strncat(dest, pre, sizeof pre);
strncat(dest, src, strlen(src) \- strlen(post));
- strncat(dest, new_post, nitems(new_post));
+ strncat(dest, new_post, sizeof new_post);
\&
puts(dest); // "pre.some_long_body.foo.bar"
free(dest);
- exit(EXIT_SUCCESS);
}
.EE
.\" SRC END
.in
.SH SEE ALSO
.BR string (3),
-.BR string_copying (3)
+.BR string_copying (7)
--
2.41.0