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