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.