Module Name:    src
Committed By:   martin
Date:           Fri Sep 20 11:22:29 UTC 2024

Modified Files:
        src/lib/libc/string [netbsd-10]: Makefile.inc strcpy.3 strlcpy.3
Added Files:
        src/lib/libc/string [netbsd-10]: strncpy.3

Log Message:
Pull up following revision(s) (requested by rin in ticket #891):

        lib/libc/string/strncpy.3: revision 1.10
        lib/libc/string/strncpy.3: revision 1.11
        lib/libc/string/strncpy.3: revision 1.12
        lib/libc/string/strncpy.3: revision 1.13
        lib/libc/string/strncpy.3: revision 1.14
        lib/libc/string/strncpy.3: revision 1.15
        lib/libc/string/strlcpy.3: revision 1.20
        lib/libc/string/strncpy.3: revision 1.16
        lib/libc/string/strncpy.3: revision 1.1
        lib/libc/string/strlcpy.3: revision 1.21
        lib/libc/string/strncpy.3: revision 1.2
        lib/libc/string/strncpy.3: revision 1.3
        lib/libc/string/strncpy.3: revision 1.4
        lib/libc/string/strncpy.3: revision 1.5
        lib/libc/string/strncpy.3: revision 1.6
        lib/libc/string/Makefile.inc: revision 1.88
        lib/libc/string/strncpy.3: revision 1.7
        lib/libc/string/Makefile.inc: revision 1.89
        lib/libc/string/strncpy.3: revision 1.8
        lib/libc/string/strncpy.3: revision 1.9
        lib/libc/string/strcpy.3: revision 1.24
        lib/libc/string/strcpy.3: revision 1.25
        lib/libc/string/strcpy.3: revision 1.26
        lib/libc/string/strcpy.3: revision 1.27
        lib/libc/string/strlcpy.3: revision 1.15
        lib/libc/string/strlcpy.3: revision 1.16
        lib/libc/string/strlcpy.3: revision 1.17
        lib/libc/string/strlcpy.3: revision 1.18
        lib/libc/string/strlcpy.3: revision 1.19

strlcpy(3): Rework man page to clarify relation to strncpy(3).

Add caveats explaining when strlcpy(3) and strlcat(3) are dangerously
inadequate or inappropriate.

strncpy(3), stpncpy(3): Split man page out of strcpy(3), stpcpy(3).

These are for substantively different purposes (fixed-width fields
with optional NUL padding vs NUL-terminated strings), so they don't
belong together.

Be more specific about the security issues.

strncpy(3): Qualify example of strlcpy(3) with a major caveat.

strncpy(3): Slightly more consistency about NUL vs '\0' in the text.

Install strncpy.3 to fix build
strncpy(3): use .Sm off/on around a fancy expression to avoid lots of Ns
strncpy(3): markup tweaks

NUL is a character name, not a defined name, use .Tn
.Ns has implicit .No effect

Use \*q for ASCII quotes (.Dq uses fancy typographical ones)
strcpy(3), strlcpy(3), strncpy(3): Use `.Tn NUL' for the zero byte.

Let's be consistent within these man pages.  (If someone else really
likes the unpronounceable `.Ql \e0' better, that's fine, you can go
through and systematically change all the man pages to use that after
we're done clarifying strcpy(3), strncpy(3), and strlcpy(3).)

strncpy(3): Note strcpy(3) man page revision this forked from.

strncpy(3): Rework the example in an attempt to improve exposition.

strcpy(3): Note that strlcpy(3) is a safer replacement for strcpy(3).

Suggest snprintf("%s") as a more portable alternative too.

Note that both strlcpy and snprintf still require the input to be
NUL-terminated.

strlcpy(3): don't use \*[Ge] for >= - it's wrong for source code

In the PostScript output it produces the single mathematical "greater
or equal" symbol, not the ">=".

strlcpy(3): Nix stray space between `NUL' and `-terminating'.

strncpy(3): Take another whack at clarifying this.

Emphasize the fixed-buffer nature of it, and that NUL-termination is
neither required on input nor guaranteed on output.

strncpy(3): Fix typo -- stpncpy, not stpcpy which is different.

strncpy(3): Reword to make sentence structure parallel.

strncpy(3): Tiny wording tweak.

strcpy(3), strlcpy(3), strncpy(3): Just say `byte', not `character'.

strlcpy(3), strncpy(3): Omit needless (void) casts in examples.
The return values are not critical.

strlcpy(3): Tweak markup.

strncpy(3): Fix column sizing.

strncpy(3): More on how strlcpy is not a safe strncpy replacement.


To generate a diff of this commit:
cvs rdiff -u -r1.85 -r1.85.6.1 src/lib/libc/string/Makefile.inc
cvs rdiff -u -r1.23 -r1.23.26.1 src/lib/libc/string/strcpy.3
cvs rdiff -u -r1.14 -r1.14.2.1 src/lib/libc/string/strlcpy.3
cvs rdiff -u -r0 -r1.16.4.2 src/lib/libc/string/strncpy.3

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/string/Makefile.inc
diff -u src/lib/libc/string/Makefile.inc:1.85 src/lib/libc/string/Makefile.inc:1.85.6.1
--- src/lib/libc/string/Makefile.inc:1.85	Wed Apr 14 08:07:49 2021
+++ src/lib/libc/string/Makefile.inc	Fri Sep 20 11:22:29 2024
@@ -1,5 +1,5 @@
 #	from: @(#)Makefile.inc	8.1 (Berkeley) 6/4/93
-#	$NetBSD: Makefile.inc,v 1.85 2021/04/14 08:07:49 mrg Exp $
+#	$NetBSD: Makefile.inc,v 1.85.6.1 2024/09/20 11:22:29 martin Exp $
 
 # string sources
 .PATH: ${ARCHDIR}/string ${.CURDIR}/string
@@ -48,7 +48,7 @@ MAN+=	bm.3 bcmp.3 bcopy.3 bstring.3 bzer
 	popcount.3 \
 	rindex.3 strcasecmp.3 strcat.3 strchr.3 strcmp.3 strcoll.3 \
 	strcpy.3 strcspn.3 strdup.3 strerror.3 string.3 strings.3 strlcpy.3 \
-	strlen.3 strmode.3 strpbrk.3 strrchr.3 strsep.3 \
+	strlen.3 strmode.3 strncpy.3 strpbrk.3 strrchr.3 strsep.3 \
 	strsignal.3 strspn.3 strstr.3 strtok.3 strxfrm.3 \
 	swab.3 wcstok.3 wcswidth.3 wmemchr.3 wcsdup.3 wcscasecmp.3
 
@@ -60,9 +60,10 @@ MLINKS+=popcount.3 popcount64.3
 MLINKS+=strcasecmp.3 strncasecmp.3
 MLINKS+=strcat.3 strncat.3
 MLINKS+=strcmp.3 strncmp.3
-MLINKS+=strcpy.3 strncpy.3 strcpy.3 stpcpy.3 strcpy.3 stpncpy.3
+MLINKS+=strcpy.3 stpcpy.3
 MLINKS+=strlcpy.3 strlcat.3
 MLINKS+=strlen.3 strnlen.3
+MLINKS+=strncpy.3 stpncpy.3
 MLINKS+=strstr.3 strcasestr.3
 MLINKS+=strstr.3 strnstr.3
 MLINKS+=strchr.3 strchrnul.3

Index: src/lib/libc/string/strcpy.3
diff -u src/lib/libc/string/strcpy.3:1.23 src/lib/libc/string/strcpy.3:1.23.26.1
--- src/lib/libc/string/strcpy.3:1.23	Wed Apr  1 20:18:17 2015
+++ src/lib/libc/string/strcpy.3	Fri Sep 20 11:22:29 2024
@@ -30,16 +30,14 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     from: @(#)strcpy.3	8.1 (Berkeley) 6/4/93
-.\"	$NetBSD: strcpy.3,v 1.23 2015/04/01 20:18:17 riastradh Exp $
+.\"	$NetBSD: strcpy.3,v 1.23.26.1 2024/09/20 11:22:29 martin Exp $
 .\"
-.Dd April 1, 2015
+.Dd August 11, 2023
 .Dt STRCPY 3
 .Os
 .Sh NAME
 .Nm stpcpy ,
-.Nm stpncpy ,
-.Nm strcpy ,
-.Nm strncpy
+.Nm strcpy
 .Nd copy strings
 .Sh LIBRARY
 .Lb libc
@@ -48,11 +46,7 @@
 .Ft char *
 .Fn stpcpy "char * restrict dst" "const char * restrict src"
 .Ft char *
-.Fn stpncpy "char * restrict dst" "const char * restrict src" "size_t len"
-.Ft char *
 .Fn strcpy "char * restrict dst" "const char * restrict src"
-.Ft char *
-.Fn strncpy "char * restrict dst" "const char * restrict src" "size_t len"
 .Sh DESCRIPTION
 The
 .Fn stpcpy
@@ -62,165 +56,97 @@ functions
 copy the string
 .Fa src
 to
-.Fa dst
-(including the terminating
-.Ql \e0
-character).
-.Pp
-The
-.Fn stpncpy
-and
-.Fn strncpy
-functions copy at most
-.Fa len
-characters from
-.Fa src
-into
-.Fa dst .
-If
-.Fa src
-is less than
-.Fa len
-characters long,
-the remainder of
-.Fa dst
-is filled with
-.Ql \e0
-characters.
-Otherwise,
-.Fa dst
-is
-.Em not
-terminated.
+.Fa dst ,
+including the terminating
+.Tn NUL
+byte.
 .Pp
 The strings
 .Fa src
 and
 .Fa dst
 may not overlap.
+The string
+.Fa src
+must be terminated by a
+.Tn NUL
+byte.
+The memory for
+.Fa dst
+must have space for
+.Fn strlen src Li "+ 1"
+bytes.
 .Sh RETURN VALUES
 The
 .Fn strcpy
-and
-.Fn strncpy
-functions
-return
+function returns
 .Fa dst .
+.Pp
 The
 .Fn stpcpy
-and
-.Fn stpncpy
-functions return a pointer to the terminating
-.Ql \e0
-character of
+function returns a pointer to the terminating
+.Tn NUL
+byte of
 .Fa dst .
-If
-.Fn stpncpy
-does not terminate
-.Fa dst
-with a
-.Dv NUL
-character, it instead returns a pointer to
-.Li dst[len]
-(which does not necessarily refer to a valid memory location.)
-.Sh EXAMPLES
-The following sets
-.Va chararray
-to
-.Dq Li abc\e0\e0\e0 :
-.Bd -literal -offset indent
-char chararray[6];
-
-(void)strncpy(chararray, "abc", sizeof(chararray));
-.Ed
-.Pp
-The following sets
-.Va chararray
-to
-.Dq Li abcdef :
-.Bd -literal -offset indent
-char chararray[6];
-
-(void)strncpy(chararray, "abcdefgh", sizeof(chararray));
-.Ed
-.Pp
-Note that it does
-.Em not
-.Dv NUL Ns No -terminate
-.Va chararray
-because the length of the source string is greater than or equal
-to the length parameter.
-.Fn strncpy
-.Em only
-.Dv NUL Ns No -terminates
-the destination string when the length of the source
-string is less than the length parameter.
-.Pp
-The following copies as many characters from
-.Va input
-to
-.Va buf
-as will fit and
-.Dv NUL Ns No -terminates
-the result.
-Because
-.Fn strncpy
-does
-.Em not
-guarantee to
-.Dv NUL Ns No -terminate
-the string itself, this must be done explicitly.
-.Bd -literal -offset indent
-char buf[1024];
-
-(void)strncpy(buf, input, sizeof(buf) - 1);
-buf[sizeof(buf) - 1] = '\e0';
-.Ed
-.Pp
-This could be better and more simply achieved using
-.Xr strlcpy 3 ,
-as shown in the following example:
-.Bd -literal -offset indent
-(void)strlcpy(buf, input, sizeof(buf));
-.Ed
-.Pp
-Note that because
-.Xr strlcpy 3
-is not defined in any standards, it should
-only be used when portability is not a concern.
 .Sh SEE ALSO
 .Xr bcopy 3 ,
 .Xr memccpy 3 ,
 .Xr memcpy 3 ,
 .Xr memmove 3 ,
 .Xr strlcpy 3 ,
+.Xr strncpy 3 ,
 .Xr wcscpy 3
 .Sh STANDARDS
 The
 .Fn strcpy
-and
-.Fn strncpy
-functions
-conform to
+function conforms to
 .St -isoC-99 .
+.Pp
 The
 .Fn stpcpy
-and
-.Fn stpncpy
-functions conform to
+function conforms to
 .St -p1003.1-2008 .
 .Sh HISTORY
 The
 .Fn stpcpy
-and
-.Fn stpncpy
-functions first appeared in
+function first appeared in
 .Nx 6.0 .
 .Sh SECURITY CONSIDERATIONS
 The
 .Fn strcpy
 and
 .Fn stpcpy
-functions are easily misused in a manner which enables malicious users
-to arbitrarily change a running program's functionality through a
-buffer overflow attack.
+functions copy until a
+.Tn NUL
+terminator without any bounds checks on the size of the input or output
+buffers.
+If the input buffer is missing a
+.Tn NUL
+terminator, or the input string is longer than the output buffer, this
+can lead to crashes or security vulnerabilities from buffer overruns,
+including disclosure of secrets in memory and arbitrary code
+execution.
+.Pp
+The
+.Xr strlcpy 3
+function is a safer replacement for
+.Fn strcpy
+which allows the caller to specify the space allocated for
+.Fa dst .
+.Xr strlcpy 3 ,
+or
+.Xr snprintf 3
+with a format string of
+.Li \*q%s\*q ,
+should be used instead of
+.Fn strcpy
+and
+.Fn stpcpy
+wherever possible to avoid buffer overruns in
+.Fa dst .
+.Po
+However, they still require
+.Fa src
+to be
+.Tn NUL Ns -terminated .
+.Pc

Index: src/lib/libc/string/strlcpy.3
diff -u src/lib/libc/string/strlcpy.3:1.14 src/lib/libc/string/strlcpy.3:1.14.2.1
--- src/lib/libc/string/strlcpy.3:1.14	Sun Aug 28 10:48:16 2022
+++ src/lib/libc/string/strlcpy.3	Fri Sep 20 11:22:29 2024
@@ -1,4 +1,4 @@
-.\"	$NetBSD: strlcpy.3,v 1.14 2022/08/28 10:48:16 hgutch Exp $
+.\"	$NetBSD: strlcpy.3,v 1.14.2.1 2024/09/20 11:22:29 martin Exp $
 .\" from OpenBSD: strlcpy.3,v 1.11 2000/11/16 23:27:41 angelos Exp
 .\"
 .\" Copyright (c) 1998, 2000 Todd C. Miller <todd.mil...@courtesan.com>
@@ -26,7 +26,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd March 1, 2001
+.Dd August 11, 2023
 .Dt STRLCPY 3
 .Os
 .Sh NAME
@@ -46,26 +46,76 @@ The
 .Fn strlcpy
 and
 .Fn strlcat
-functions copy and concatenate strings respectively.
-They are designed
-to be safer, more consistent, and less error prone replacements for
+functions copy and concatenate
+.Tn NUL Ns -terminated
+strings respectively.
+.Pp
+The
+.Fn strlcpy
+function copies up to
+.Fa size Li "- 1"
+bytes from the
+.Tn NUL Ns -terminated
+string
+.Fa src
+to
+.Fa dst ,
+.Tn NUL Ns -terminating
+the result.
+.Pp
+The
+.Fn strlcat
+function appends the
+.Tn NUL Ns -terminated
+string
+.Fa src
+to the end of
+.Fa dst .
+It will append at most
+.Fa size Li "-" Fn strlen dst Li "- 1"
+bytes,
+.Tn NUL Ns -terminating
+the result.
+.Ss Relation to Xr strncpy 3 and Xr strncat 3
+Unlike
 .Xr strncpy 3
 and
-.Xr strncat 3 .
-Unlike those functions,
+.Xr strncat 3 ,
 .Fn strlcpy
 and
 .Fn strlcat
-take the full size of the buffer (not just the length) and guarantee to
-NUL-terminate the result (as long as
+are guaranteed to
+.Tn NUL Ns -terminate
+the result (as long as
 .Fa size
 is larger than 0 or, in the case of
 .Fn strlcat ,
 as long as there is at least one byte free in
 .Fa dst ) .
-Note that you should include a byte for the NUL in
+Note that you should include a byte for the
+.Tn NUL
+in
 .Fa size .
-Also note that
+.Pp
+.Sy WARNING :
+Also unlike
+.Xr strncpy 3
+and
+.Xr strncat 3 ,
+.Fn strlcpy
+and
+.Fn strlcat
+are not guaranteed to initialize all
+.Fa size
+bytes of
+.Fa dst
+\(em bytes past
+.Fa dst Ns Li "[" Fn strlen src Li "+ 1" Ns Li "]"
+are left uninitialized.
+This can lead to security vulnerabilities such as leaking secrets from
+uninitialized stack or heap buffers.
+.Pp
+.Sy WARNING :
 .Fn strlcpy
 and
 .Fn strlcat
@@ -75,33 +125,32 @@ strings.
 This means that for
 .Fn strlcpy
 .Fa src
-must be NUL-terminated and for
+must be
+.Tn NUL Ns -terminated
+and for
 .Fn strlcat
 both
 .Fa src
 and
 .Fa dst
-must be NUL-terminated.
-.Pp
-The
+must be
+.Tn NUL Ns -terminated .
+Applications handling fixed-width fields with
+.Pq possibly empty
+.Tn NUL
+padding, instead of
+.Tn NUL Ns -terminated
+C strings, MUST use
+.Xr strncpy 3
+and
+.Xr strncat 3
+instead.
+Attempting to use
 .Fn strlcpy
-function copies up to
-.Fa size
-- 1 characters from the NUL-terminated string
-.Fa src
-to
-.Fa dst ,
-NUL-terminating the result.
-.Pp
-The
+or
 .Fn strlcat
-function appends the NUL-terminated string
-.Fa src
-to the end of
-.Fa dst .
-It will append at most
-.Fa size
-- strlen(dst) - 1 bytes, NUL-terminating the result.
+for these cases can lead to crashes or security vulnerabilities from
+buffer overruns.
 .Sh RETURN VALUES
 The
 .Fn strlcpy
@@ -126,11 +175,13 @@ Note however, that if
 .Fn strlcat
 traverses
 .Fa size
-characters without finding a NUL, the length of the string is considered
-to be
+bytes without finding a
+.Tn NUL ,
+the length of the string is considered to be
 .Fa size
-and the destination string will not be NUL-terminated (since there was
-no space for the NUL).
+and the destination string will not be
+.Tn NUL Ns -terminated
+.Pq since there was no space for the Tn NUL .
 This keeps
 .Fn strlcat
 from running off the end of a string.
@@ -149,8 +200,8 @@ char *s, *p, buf[BUFSIZ];
 
 \&...
 
-(void)strlcpy(buf, s, sizeof(buf));
-(void)strlcat(buf, p, sizeof(buf));
+strlcpy(buf, s, sizeof(buf));
+strlcat(buf, p, sizeof(buf));
 .Ed
 .Pp
 To detect truncation, perhaps while building a pathname, something
@@ -166,7 +217,7 @@ if (strlcat(pname, file, sizeof(pname)) 
 	goto toolong;
 .Ed
 .Pp
-Since we know how many characters we copied the first time, we can
+Since we know how many bytes we copied the first time, we can
 speed things up a bit by using a copy instead of an append:
 .Bd -literal -offset indent
 char *dir, *file, pname[MAXPATHLEN];
@@ -175,9 +226,9 @@ size_t n;
 \&...
 
 n = strlcpy(pname, dir, sizeof(pname));
-if (n \*[Ge] sizeof(pname))
+if (n >= sizeof(pname))
 	goto toolong;
-if (strlcpy(pname + n, file, sizeof(pname) - n) \*[Ge] sizeof(pname) - n)
+if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n)
 	goto toolong;
 .Ed
 .Pp

Added files:

Index: src/lib/libc/string/strncpy.3
diff -u /dev/null src/lib/libc/string/strncpy.3:1.16.4.2
--- /dev/null	Fri Sep 20 11:22:29 2024
+++ src/lib/libc/string/strncpy.3	Fri Sep 20 11:22:29 2024
@@ -0,0 +1,302 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     from: @(#)strcpy.3	8.1 (Berkeley) 6/4/93
+.\"     from: NetBSD: strcpy.3,v 1.23 2015/04/01 20:18:17 riastradh Exp
+.\"	$NetBSD: strncpy.3,v 1.16.4.2 2024/09/20 11:22:29 martin Exp $
+.\"
+.Dd August 11, 2023
+.Dt STRNCPY 3
+.Os
+.Sh NAME
+.Nm stpncpy ,
+.Nm strncpy
+.Nd copy fixed-width buffers with NUL padding
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft char *
+.Fn stpncpy "char * restrict dst" "const char * restrict src" "size_t len"
+.Ft char *
+.Fn strncpy "char * restrict dst" "const char * restrict src" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn stpncpy
+and
+.Fn strncpy
+functions fill a
+.Fa len Ns -byte
+buffer at
+.Fa dst
+by copying up to
+.Fa len
+.No non- Ns Tn NUL
+bytes from
+.Fa src
+followed by enough
+.Tn NUL
+bytes \(em possibly zero of them \(em to pad the remainder.
+.Pp
+The buffers
+.Fa src
+and
+.Fa dst
+may not overlap.
+.Pp
+The buffer
+.Fa src
+is not required to hold a
+.Tn NUL Ns -terminated
+string on input; it is only required
+.Em either
+to have at least
+.Fa len
+bytes allocated and initialized,
+.Em or
+to have a
+.Tn NUL
+byte if it is shorter than
+.Fa len
+bytes.
+.Pp
+The buffer
+.Fa dst
+is not guaranteed to hold a
+.Tn NUL Ns -terminated
+string on output;
+.Fn stpncpy
+and
+.Fn strncpy
+write exactly
+.Fa len
+bytes to it, which includes nonempty
+.Tn NUL
+padding only if a
+.Tn NUL
+byte appears in the first
+.Fa len
+bytes at
+.Fa src .
+.Sh RETURN VALUES
+The
+.Fn strncpy
+function returns
+.Fa dst .
+.Pp
+The
+.Fn stpncpy
+function returns a pointer to the byte after the last
+.No non- Ns Tn NUL
+byte of
+.Fa dst .
+This does not necessarily point to a
+.Tn NUL
+byte;
+.Fn stpncpy
+may return
+.Li \*(Am Ns Fa dst Ns Li "[" Fa len Ns Li "]" Ns ,
+if all
+.Fa len
+bytes starting at
+.Fa src
+are
+.No non- Tn NUL .
+.Sh EXAMPLES
+The following logic fills a fixed-width field in a record that might
+appear on disk with the content of a caller-provided string
+.Dv str ,
+padded to the end of the field with
+.Tn NUL
+bytes:
+.Bd -literal -offset indent
+struct record {
+	uint16_t	id;
+	char		name[6];
+	uint8_t		tag;
+	...
+};
+
+struct record *rec = ...;
+strncpy(rec->name, str, sizeof(rec->name));
+.Ed
+.Pp
+The following values for
+.Dv str
+result in the following corresponding contents of
+.Dv rec Ns Li "->name" :
+.Bl -column -offset indent ".Li \*qabcdefghi\e0\*q" ".Li \*qabc\e0\e0\e0\*q"
+.It Dv str Ta Dv rec Ns Li "->name"
+.It Li \*qabc\e0\*q Ta Li \*qabc\e0\e0\e0\*q
+.It Li \*qabc\e0\e0\e0\*q Ta Li \*qabc\e0\e0\e0\*q
+.It Li \*qabcde\e0\*q Ta Li \*qabcde\e0\*q
+.It Li \*qabcdef\e0\*q Ta Li \*qabcdef\*q
+.It Li \*qabcdef\*q Ta Li \*qabcdef\*q
+.It Li \*qabcdefghi\e0\*q Ta Li \*qabcdef\*q
+.It Li \*qabcdefghi\*q Ta Li \*qabcdef\*q
+.El
+.Pp
+Note that when
+.Dv str
+has at least six
+.No non- Ns Tn NUL
+bytes,
+.Dv rec Ns Li "->name"
+is
+.Em not
+.Tn NUL Ns -terminated
+\(em it is only
+.Em padded
+with (possibly zero)
+.Tn NUL
+bytes to fill the fixed-width buffer.
+When
+.Dv str
+has
+.Em more
+than six
+.No non- Ns Tn NUL
+bytes, the additional ones are truncated.
+If
+.Dv str
+has space for
+.Em fewer
+than six bytes, and the last one is not
+.Tn NUL ,
+using
+.Fn strncpy
+is undefined.
+.Pp
+Because
+.Fn strncpy
+does
+.Em not
+guarantee to
+.Tn NUL Ns -terminate
+the result, if
+.Tn NUL Ns -termination
+is required it must be done explicitly:
+.Bd -literal -offset indent
+char buf[1024];
+
+strncpy(buf, input, sizeof(buf) - 1);
+buf[sizeof(buf) - 1] = '\e0';
+.Ed
+.Pp
+If
+.Va input
+is guaranteed to be
+.Tn NUL Ns -terminated ,
+and if
+.Va buf
+need only be
+.Tn NUL Ns -terminated ,
+not fully initialized with
+.Tn NUL
+padding,
+this could be achieved using
+.Xr strlcpy 3
+as follows:
+.Bd -literal -offset indent
+strlcpy(buf, input, sizeof(buf));
+.Ed
+.Pp
+It is not enough for
+.Va input
+to have
+.Li sizeof(buf)
+bytes allocated; it MUST be
+.Tn NUL Ns -terminated
+for
+.Xr strlcpy 3
+to be used.
+.Pp
+Note that because
+.Xr strlcpy 3
+is not defined in any standards, it should
+only be used when portability is not a concern.
+.Pp
+.Sy WARNING :
+Because
+.Xr strlcpy 3
+does not fully initialize
+.Fa dst ,
+but does read all the way to a
+.Tn NUL
+terminator in
+.Fa src
+even past
+.Fa len
+bytes,
+.Xr strlcpy 3
+is
+.Em not
+a safe
+.Tn NUL Ns -terminating
+replacement for
+.Fn strncpy .
+Naively replacing
+.Fn strncpy
+by
+.Xr strlcpy 3
+can lead to crashes, undefined behaviour, and disclosure of secrets
+from uninitialized memory.
+.Sh SEE ALSO
+.Xr bcopy 3 ,
+.Xr memccpy 3 ,
+.Xr memcpy 3 ,
+.Xr memmove 3 ,
+.Xr strcpy 3 ,
+.Xr strlcpy 3 ,
+.Xr wcscpy 3
+.Sh STANDARDS
+The
+.Fn strncpy
+function conforms to
+.St -isoC-99 .
+.Pp
+The
+.Fn stpncpy
+function conforms to
+.St -p1003.1-2008 .
+.Sh HISTORY
+The
+.Fn stpncpy
+function first appeared in
+.Nx 6.0 .
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn stpncpy
+and
+.Fn strncpy
+functions are not guaranteed to
+.Tn NUL Ns -terminate
+the result.

Reply via email to