Use OpenBSD's revamped description of strlcpy and strlcat.
This explanation is supposed to be simpler and better. In particular "comparing it to the snprintf API provides lots of value, since it raises the bar on understanding, so that programmers/auditors will a better job calling all 3 of these functions." Requested by: deraadt@cvs.openbsd.org Obtained From: OpenBSD Reviewed by: cperciva
This commit is contained in:
parent
023fc3804d
commit
fc81a90261
@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: strlcpy.3,v 1.19 2007/05/31 19:19:32 jmc Exp $
|
||||
.\" $OpenBSD: strlcpy.3,v 1.26 2013/09/30 12:02:35 millert Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1998, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
.\"
|
||||
@ -27,7 +27,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 22, 1998
|
||||
.Dd November 10, 2013
|
||||
.Dt STRLCPY 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -47,69 +47,81 @@ 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 strings with the
|
||||
same input parameters and output result as
|
||||
.Xr snprintf 3 .
|
||||
They are designed to be safer, more consistent, and less error
|
||||
prone replacements for the easily misused functions
|
||||
.Xr strncpy 3
|
||||
and
|
||||
.Xr strncat 3 .
|
||||
Unlike those functions,
|
||||
.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
|
||||
.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 a byte for the NUL should be included in
|
||||
.Fa size .
|
||||
Also note that
|
||||
.Fn strlcpy
|
||||
and
|
||||
.Fn strlcat
|
||||
only operate on true
|
||||
.Dq C
|
||||
strings.
|
||||
This means that for
|
||||
.Fn strlcpy
|
||||
.Fa src
|
||||
must be NUL-terminated and for
|
||||
.Fn strlcat
|
||||
both
|
||||
.Fa src
|
||||
and
|
||||
.Fa dst
|
||||
must be NUL-terminated.
|
||||
.Pp
|
||||
The
|
||||
.Fn strlcpy
|
||||
function copies up to
|
||||
.Fa size
|
||||
- 1 characters from the NUL-terminated string
|
||||
and
|
||||
.Fn strlcat
|
||||
take the full size of the destination buffer and guarantee
|
||||
NUL-termination if there is room.
|
||||
Note that room for the NUL should be included in
|
||||
.Fa dstsize .
|
||||
.Pp
|
||||
.Fn strlcpy
|
||||
copies up to
|
||||
.Fa dstsize
|
||||
\- 1 characters from the string
|
||||
.Fa src
|
||||
to
|
||||
.Fa dst ,
|
||||
NUL-terminating the result.
|
||||
NUL-terminating the result if
|
||||
.Fa dstsize
|
||||
is not 0.
|
||||
.Pp
|
||||
The
|
||||
.Fn strlcat
|
||||
function appends the NUL-terminated string
|
||||
appends string
|
||||
.Fa src
|
||||
to the end of
|
||||
.Fa dst .
|
||||
It will append at most
|
||||
.Fa size
|
||||
- strlen(dst) - 1 bytes, NUL-terminating the result.
|
||||
.Fa dstsize
|
||||
\- strlen(dst) \- 1 characters.
|
||||
It will then NUL-terminate, unless
|
||||
.Fa dstsize
|
||||
is 0 or the original
|
||||
.Fa dst
|
||||
string was longer than
|
||||
.Fa dstsize
|
||||
(in practice this should not happen
|
||||
as it means that either
|
||||
.Fa dstsize
|
||||
is incorrect or that
|
||||
.Fa dst
|
||||
is not a proper string).
|
||||
.Pp
|
||||
If the
|
||||
.Fa src
|
||||
and
|
||||
.Fa dst
|
||||
strings overlap, the behavior is undefined.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
Besides quibbles over the return type
|
||||
.Pf ( Va size_t
|
||||
versus
|
||||
.Va int )
|
||||
and signal handler safety
|
||||
.Pf ( Xr snprintf 3
|
||||
is not entirely safe on some systems), the
|
||||
following two are equivalent:
|
||||
.Bd -literal -offset indent
|
||||
n = strlcpy(dst, src, len);
|
||||
n = snprintf(dst, len, "%s", src);
|
||||
.Ed
|
||||
.Pp
|
||||
Like
|
||||
.Xr snprintf 3 ,
|
||||
the
|
||||
.Fn strlcpy
|
||||
and
|
||||
.Fn strlcat
|
||||
functions return the total length of the string they tried to
|
||||
create.
|
||||
functions return the total length of the string they tried to create.
|
||||
For
|
||||
.Fn strlcpy
|
||||
that means the length of
|
||||
@ -121,29 +133,12 @@ that means the initial length of
|
||||
plus
|
||||
the length of
|
||||
.Fa src .
|
||||
While this may seem somewhat confusing, it was done to make
|
||||
truncation detection simple.
|
||||
.Pp
|
||||
Note however, that if
|
||||
.Fn strlcat
|
||||
traverses
|
||||
.Fa size
|
||||
characters without finding a 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).
|
||||
This keeps
|
||||
.Fn strlcat
|
||||
from running off the end of a string.
|
||||
In practice this should not happen (as it means that either
|
||||
.Fa size
|
||||
is incorrect or that
|
||||
.Fa dst
|
||||
is not a proper
|
||||
.Dq C
|
||||
string).
|
||||
The check exists to prevent potential security problems in incorrect code.
|
||||
If the return value is
|
||||
.Cm >=
|
||||
.Va dstsize ,
|
||||
the output string has been truncated.
|
||||
It is the caller's responsibility to handle this.
|
||||
.Sh EXAMPLES
|
||||
The following code fragment illustrates the simple case:
|
||||
.Bd -literal -offset indent
|
||||
@ -169,7 +164,7 @@ if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
|
||||
.Ed
|
||||
.Pp
|
||||
Since it is known how many characters were copied the first time, things
|
||||
can be sped up a bit by using a copy instead of an append.
|
||||
can be sped up a bit by using a copy instead of an append:
|
||||
.Bd -literal -offset indent
|
||||
char *dir, *file, pname[MAXPATHLEN];
|
||||
size_t n;
|
||||
@ -201,5 +196,5 @@ and
|
||||
.Fn strlcat
|
||||
functions first appeared in
|
||||
.Ox 2.4 ,
|
||||
and made their appearance in
|
||||
and
|
||||
.Fx 3.3 .
|
||||
|
Loading…
Reference in New Issue
Block a user