1.\" $NetBSD: strlcpy.3,v 1.25 2025/04/02 00:50:19 gutteridge Exp $ 2.\" from OpenBSD: strlcpy.3,v 1.11 2000/11/16 23:27:41 angelos Exp 3.\" 4.\" Copyright (c) 1998, 2000 Todd C. Miller <Todd.Miller@courtesan.com> 5.\" All rights reserved. 6.\" 7.\" Redistribution and use in source and binary forms, with or without 8.\" modification, are permitted provided that the following conditions 9.\" are met: 10.\" 1. Redistributions of source code must retain the above copyright 11.\" notice, this list of conditions and the following disclaimer. 12.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" notice, this list of conditions and the following disclaimer in the 14.\" documentation and/or other materials provided with the distribution. 15.\" 3. The name of the author may not be used to endorse or promote products 16.\" derived from this software without specific prior written permission. 17.\" 18.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 19.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 20.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28.\" 29.Dd March 30, 2025 30.Dt STRLCPY 3 31.Os 32.Sh NAME 33.Nm strlcpy , 34.Nm strlcat 35.Nd size-bounded string copying and concatenation 36.Sh LIBRARY 37.Lb libc 38.Sh SYNOPSIS 39.In string.h 40.Ft size_t 41.Fn strlcpy "char *dst" "const char *src" "size_t size" 42.Ft size_t 43.Fn strlcat "char *dst" "const char *src" "size_t size" 44.Sh DESCRIPTION 45The 46.Fn strlcpy 47and 48.Fn strlcat 49functions copy and concatenate 50.Tn NUL Ns -terminated 51strings respectively. 52.Pp 53The 54.Fn strlcpy 55function computes the length 56.Pq like Xr strlen 3 57of 58.Fa src , 59which 60.Em MUST 61be 62.Tn NUL Ns -terminated , 63and copies up to 64.Fa size Li "- 1" 65bytes from 66.Fa src 67to 68.Fa dst , 69.Tn NUL Ns -terminating 70the result. 71.Pp 72If the bytes 73.Fa dst Ns Li "[0]" , 74.Fa dst Ns Li "[1]" , 75\&..., 76.Fa dst Ns Li "[" Ns Fa size Li - 1 Ns Li "]" 77are all 78.No non- Ns Tn NUL , 79then the 80.Fn strlcat 81function returns 82.Fa size + Fn strlen src 83without writing anything to 84.Fa dst . 85.Pp 86Otherwise, the 87.Fn strlcat 88function computes the sum of the lengths of 89.Fa dst 90and 91.Fa src , 92which 93.Em MUST 94be 95.Tn NUL Ns -terminated , 96and copies the content of 97.Fa src 98to the position of the first 99.Tn NUL 100byte in 101.Fa dst , 102.Tn NUL Ns -terminating 103the result. 104.Fn strlcat 105will append at most 106.Fa size Li "-" Fn strlen dst Li "- 1" 107.No non- Ns Tn NUL 108bytes from 109.Fa src , 110followed by one 111.Ns NUL 112byte. 113.Ss Relation to Xr strncpy 3 and Xr strncat 3 114Unlike 115.Xr strncpy 3 , 116.Fn strlcpy 117is guaranteed to 118.Tn NUL Ns -terminate 119the result (as long as 120.Fa size 121is larger than 0). 122Note that you should include a byte for the 123.Tn NUL 124in 125.Fa size . 126.Pp 127Unlike 128.Xr strncat 3 , 129.Fn strlcat 130is guaranteed to 131.Tn NUL Ns -terminate 132the result if 133.Fa dst 134is 135.Tn NUL Ns -terminated 136to begin with. 137.Pp 138.Sy WARNING : 139.Fn strlcpy 140and 141.Fn strlcat 142are not guaranteed to initialize all 143.Fa size 144bytes of 145.Fa dst 146\(em 147.Fn strlcpy 148leaves bytes past 149.Fa dst Ns Li "[" Fn strlen src Li "+ 1" Ns Li "]" 150uninitialized, and 151.Fn strlcat 152leaves bytes past 153.Fa dst Ns Li "[" Fn strlen dst Li + Fn strlen src Li + 1 Ns Li "]" 154uninitialized. 155This can lead to security vulnerabilities such as leaking secrets from 156uninitialized stack or heap buffers. 157You 158.Em MUST NOT 159simply replace 160.Xr strncpy 3 161and 162.Xr strncat 3 163by 164.Fn strlcpy 165and 166.Fn strlcat 167without proving it is safe to leave some of the output uninitialized. 168.Pp 169.Sy WARNING : 170.Fn strlcat 171does not guarantee to 172.Tn NUL Ns -terminate 173.Fa dst 174even if there is space for it. 175In particular, if 176.Fa dst 177is not 178.Tn NUL Ns -terminated 179on entry, then 180.Fn strlcat 181will leave it without a 182.Tn NUL Ns -terminator 183on return. 184.Pp 185.Sy WARNING : 186The 187.Fa src 188argument 189.Em MUST 190be 191.Tn NUL Ns -terminated . 192Both 193.Fn strlcpy 194and 195.Fn strlcat 196will read through 197.Fa src 198until they find a 199.Tn NUL 200terminator, reading 201.Fa src Ns Li "[" Ns Fa size Ns Li "]" Ns , 202.Fa src Ns Li "[" Ns Fa size Li + 1 Ns Li "]" Ns , 203.Fa src Ns Li "[" Ns Fa size Li + 2 Ns Li "]" Ns , 204and beyond if there was no earlier 205.Tn NUL 206terminator. 207Applications handling fixed-width fields with 208.Pq possibly empty 209.Tn NUL 210padding, instead of 211.Tn NUL Ns -terminated 212C strings, 213.Em MUST 214use 215.Xr strncpy 3 216and 217.Xr strncat 3 218instead. 219Attempting to use 220.Fn strlcpy 221or 222.Fn strlcat 223for these cases can lead to crashes or security vulnerabilities from 224buffer overruns. 225.Sh RETURN VALUES 226The 227.Fn strlcpy 228and 229.Fn strlcat 230functions return the total length of the string they tried to create. 231For 232.Fn strlcpy 233that means the length of 234.Fa src . 235For 236.Fn strlcat 237that means the initial length of 238.Fa dst 239plus 240the length of 241.Fa src . 242While this may seem somewhat confusing it was done to make 243truncation detection simple. 244.Pp 245Note however, that if 246.Fn strlcat 247traverses 248.Fa size 249bytes without finding a 250.Tn NUL , 251the length of the string is considered to be 252.Fa size 253and the destination string will not be 254.Tn NUL Ns -terminated 255.Pq since there was no space for the Tn NUL . 256This keeps 257.Fn strlcat 258from running off the end of a string. 259In practice this should not happen (as it means that either 260.Fa size 261is incorrect or that 262.Fa dst 263is not a proper 264.Dq C 265string). 266The check exists to prevent potential security problems in incorrect code. 267.Sh EXAMPLES 268The following code fragment illustrates the simple case: 269.Bd -literal -offset indent 270char *s, *p, buf[BUFSIZ]; 271 272\&... 273 274strlcpy(buf, s, sizeof(buf)); 275strlcat(buf, p, sizeof(buf)); 276.Ed 277.Pp 278To detect truncation, perhaps while building a pathname, something 279like the following might be used: 280.Bd -literal -offset indent 281char *dir, *file, pname[MAXPATHLEN]; 282 283\&... 284 285if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname)) 286 goto toolong; 287if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname)) 288 goto toolong; 289.Ed 290.Pp 291Since we know how many bytes we copied the first time, we can 292speed things up a bit by using a copy instead of an append: 293.Bd -literal -offset indent 294char *dir, *file, pname[MAXPATHLEN]; 295size_t n; 296 297\&... 298 299n = strlcpy(pname, dir, sizeof(pname)); 300if (n >= sizeof(pname)) 301 goto toolong; 302if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n) 303 goto toolong; 304.Ed 305.Pp 306However, one may question the validity of such optimizations, as they 307defeat the whole purpose of 308.Fn strlcpy 309and 310.Fn strlcat . 311.Sh SEE ALSO 312.Xr snprintf 3 , 313.Xr strncat 3 , 314.Xr strncpy 3 315.Rs 316.%A Todd C. Miller 317.%A Theo de Raadt 318.%T strlcpy and strlcat -- Consistent, Safe, String Copy and Concatenation 319.%I USENIX Association 320.%B Proceedings of the FREENIX Track: 1999 USENIX Annual Technical Conference 321.%D June 6-11, 1999 322.%U http://www.usenix.org/publications/library/proceedings/usenix99/full_papers/millert/millert.pdf 323.Re 324.Sh STANDARDS 325The 326.Fn strlcpy 327and 328.Fn strlcat 329functions conform to 330.St -p1003.1-2024 . 331.Sh HISTORY 332The 333.Fn strlcpy 334and 335.Fn strlcat 336functions first appeared in 337.Ox 2.4 , 338then in 339.Nx 1.4.3 340and 341.Fx 3.3 . 342