STRLCPY(3)

STRLCPY(3) | Library Functions Manual | STRLCPY(3)

# NAME

`strlcpy`, `strlcat` — size-bounded string copying and concatenation

# LIBRARY

Standard C Library (libc, -lc)

# 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);

# DESCRIPTION

The `strlcpy`() and `strlcat`() functions copy and concatenate NUL-terminated strings respectively.

The `strlcpy`() function computes the length (like strlen(3)) of src, which MUST be NUL-terminated, and copies up to size `- 1` bytes from src to dst, NUL-terminating the result.

If the bytes dst`[0]`, dst`[1]`, ..., dst[size `- 1`] are all non-NUL, then the `strlcat`() function returns size `+` `strlen`(src) without writing anything to dst.

Otherwise, the `strlcat`() function computes the sum of the lengths of dst and src, which MUST be NUL-terminated, and copies the content of src to the position of the first NUL byte in dst, NUL-terminating the result. `strlcat`() will append at most size `-` `strlen`(dst) `- 1` non-NUL bytes from src, followed by one NUL byte.

## Relation to strncpy(3) and strncat(3)

Unlike strncpy(3), `strlcpy`() is guaranteed to NUL-terminate the result (as long as size is larger than 0). Note that you should include a byte for the NUL in size.

Unlike strncat(3), `strlcat`() is guaranteed to NUL-terminate the result if dst is NUL-terminated to begin with.

WARNING: `strlcpy`() and `strlcat`() are not guaranteed to initialize all size bytes of dst — `strlcpy`() leaves bytes past dst[`strlen`(src)] uninitialized, and `strlcat`() leaves bytes past dst[`strlen`(dst) `+` `strlen`(src)] uninitialized. This can lead to security vulnerabilities such as leaking secrets from uninitialized stack or heap buffers. You MUST NOT simply replace strncpy(3) and strncat(3) by `strlcpy`() and `strlcat`() without proving it is safe to leave some of the output uninitialized.

WARNING: `strlcat`() does not guarantee to NUL-terminate dst even if there is space for it. In particular, if dst is not NUL-terminated on entry, then `strlcat`() will leave it without a NUL-terminator on return.

WARNING: The src argument MUST be NUL-terminated. Both `strlcpy`() and `strlcat`() will read through src until they find a NUL terminator, reading src[size], src[size `+ 1`], src[size `+ 2`], and beyond if there was no earlier NUL terminator. Applications handling fixed-width fields with (possibly empty) NUL padding, instead of NUL-terminated C strings, MUST use strncpy(3) and strncat(3) instead. Attempting to use `strlcpy`() or `strlcat`() for these cases can lead to crashes or security vulnerabilities from buffer overruns.

# RETURN VALUES

The `strlcpy`() and `strlcat`() functions return the total length of the string they tried to create. 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.

Note however, that if `strlcat`() traverses size bytes without finding a NUL, the length of the string is considered to be size and the destination string will not be NUL-terminated (since there was no space for the NUL). This keeps `strlcat`() from running off the end of a string. In practice this should not happen (as it means that either size is incorrect or that dst is not 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];

    ...

    strlcpy(buf, s, sizeof(buf));
    strlcat(buf, p, sizeof(buf));

To detect truncation, perhaps while building a pathname, something like the following might be used:

    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 bytes 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`().

# SEE ALSO

snprintf(3), strncat(3), strncpy(3)

Todd C. Miller and Theo de Raadt, strlcpy and strlcat -- Consistent, Safe, String Copy and Concatenation, Proceedings of the FREENIX Track: 1999 USENIX Annual Technical Conference, USENIX Association, http://www.usenix.org/publications/library/proceedings/usenix99/full_papers/millert/millert.pdf, June 6-11, 1999.

# STANDARDS

The `strlcpy`() and `strlcat`() functions conform to IEEE Std 1003.1-2024 (“POSIX.1”).

# HISTORY

The `strlcpy`() and `strlcat`() functions first appeared in OpenBSD 2.4, then in NetBSD 1.4.3 and FreeBSD 3.3.

January 4, 2026 | NetBSD 11.0