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 copies up to size `- 1` bytes 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.

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

Unlike strncpy(3) and strncat(3), `strlcpy`() and `strlcat`() are guaranteed to NUL-terminate the result (as long as size is larger than 0 or, in the case of `strlcat`(), as long as there is at least one byte free in dst). Note that you should include a byte for the NUL in size.

WARNING: Also unlike strncpy(3) and strncat(3), `strlcpy`() and `strlcat`() are not guaranteed to initialize all size bytes of dst — bytes past dst[`strlen`(src) `+ 1`] are left uninitialized. This can lead to security vulnerabilities such as leaking secrets from uninitialized stack or heap buffers.

WARNING: `strlcpy`() and `strlcat`() only operate 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. 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.

# HISTORY

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

August 11, 2023 | NetBSD 10.1