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 <[email protected]>
@@ -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.