![]() |
![]() |
![]() |
![]() |
strlcat(), strlcpy()
Size-bounded string copying and concatenation
Synopsis:
#include <string.h>
size_t strlcpy( char *dst,
const char *src,
size_t size );
size_t strlcat( char *dst,
const char *src,
size_t size );
Arguments:
- dst
- A pointer to the destination string.
- src
- A pointer to the source string.
- size
- The size of the destination buffer.
Library:
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
Description:
The strlcpy() and strlcat() functions copy and concatenate strings respectively. They're designed to be safer, more consistent, and less error-prone replacements for strncpy() and strncat().
Unlike those functions, strlcpy() and strlcat() take the full size of the buffer (not just the length) and guarantee to NUL-terminate the result (as long as size is larger than 0 or, in the case of strlcat(), as long as there's at least one byte free in dst).
![]() |
You should include a byte for the NUL in size. Also note that strlcpy() and strlcat() operate only on true “C” strings. This means that for strlcpy(), src must be NUL-terminated, and for strlcat(), both src and dst must be NUL-terminated. |
The strlcpy() function copies up to size − 1 characters from the NUL-terminated string src to dst, NUL-terminating the result.
The strlcat() function appends the NUL-terminated string src to the end of dst. It will append at most size − strlen(dst) − 1 bytes, NUL-terminating the result.
Returns:
The total length of the string:
- For strlcpy() that means the length of src.
- For strlcat() that means the initial length of dst plus the length of src. While this may seem somewhat confusing, it was done to make truncation detection simple.
![]() |
If strlcat() traverses size characters without finding a NUL, the length of the string is considered to be size, and the destination string isn't NUL-terminated (since there was no space for the NUL). This keeps strlcat() from running off the end of a string. In practice this shouldn't happen (as it means that either size is incorrect or that dst isn't a proper “C” string). The check exists to prevent potential security problems in incorrect code. |
Examples:
The following code fragment illustrates the simple case:
char *s, *p, buf[BUFSIZ]; ... (void)strlcpy(buf, s, sizeof(buf)); (void)strlcat(buf, p, sizeof(buf));
To detect truncation, perhaps while building a pathname, you could use something like this:
char *dir, *file, pname[MAXPATHLEN];
...
if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
goto toolong;
if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
goto toolong;
Since we know how many characters we copied the first time, we can speed things up a bit by using a copy instead of an append:
char *dir, *file, pname[MAXPATHLEN];
size_t n;
...
n = strlcpy(pname, dir, sizeof(pname));
if (n >= sizeof(pname))
goto toolong;
if (strlcpy(pname + n, file, sizeof(pname) - n) >=
sizeof(pname) - n)
goto toolong;
However, one may question the validity of such optimizations, as they defeat the whole purpose of strlcpy() and strlcat().
Classification:
| Safety: | |
|---|---|
| Cancellation point | No |
| Interrupt handler | Yes |
| Signal handler | Yes |
| Thread | Yes |
Contributing author:
OpenBSD
See also:
snprintf(), strncpy(), strncat()
![]() |
![]() |
![]() |
![]() |

![[Previous]](../prev.gif)
![[Contents]](../contents.gif)
![[Index]](../keyword_index.gif)
![[Next]](../next.gif)
