Decoding the strlcat() Function

The strlcat() function (with the L) achieves the same goal as the venerable strcat() function: to append one string onto the end of the other. The problem with strcat(), however, is that a size limitation isn’t set for the destination buffer. It’s quite possible for this buffer to overflow.

As a solution, the strlcat() function offers an additional argument, dstsize. This argument sets the length of the destination string, effectively equal to its buffer size. Here’s the function’s prototype:

size_t strlcat(char * restrict dst, const char * restrict src, size_t dstsize);

Characters from string src are appended to string dst. The dstsize argument is equal to the size of the dst buffer, which caps the number of characters copied to this size, minus one for the null character. Here’s the awkward way the man page puts it:

strlcat() appends string src to the end of dst. It will append at most dstsize – strlen(dst) – 1 characters. It will then NUL-terminate, unless dstsize is 0 or the original dst string was longer than dstsize (in practice this should not happen as it means that either dstsize is incorrect or that dst is not a proper string).

Ugh. Again, argument dstsize must be equal to the size of the dst buffer. That’s the only value it can be.

The strlcat() function returns the combined length of both src and dst strings (not counting their terminating null characters). This result is used to determine whether the final string was truncated. Here’s sample code:

#include <stdio.h>
#include <string.h>

int main()
{
    char first[] = "This is ";
    char last[] = "a potentially long string";
    int r;
    int size = 16;
    char buffer[size];

    strcpy(buffer,first);
    r = strlcat(buffer,last,size);

    puts(buffer);
    printf("Value returned: %d\n",r);
    if( r > size )
        puts("String truncated");
    else
        puts("String was fully copied");

    return(0);
}

The strlcat() function at Line 13 appends string last to string first, which has been copied into char array buffer[]. The size of the buffer[] array is set to 16, which is too short to accommodate the entire last string. Yet, because the same value, 16, is specified in the strlcat() function, a buffer overflow doesn’t occur.

A test is made at Line 17 comparing values r (returned from strlcat()) and size to determine whether the string was truncated.

Here’s sample output:

This is a poten
Value returned: 33
String truncated

The value returned (33) is equal to the size of both original strings, first and last. It’s the strlen() value, not the strings’ size in memory, which would include two more bytes for the two null characters at the end of each string.

If you modify Line 9 to change the size variable (and buffer size) to 64, the buffer is now large enough to accommodate the concatenated strings. Here’s the updated output:

This is a potentially long string
Value returned: 33
String was fully copied

Armed with all this data, it becomes a simpler task for me to craft my own, substitute strlcat() function. I present this solution in next week’s Lesson.

Leave a Reply