C Programming/string.h/strcat

From Wikibooks, open books for an open world
Jump to navigation Jump to search

In computing, the C programming language offers a library function called strcat that allows one memory block to be appended to another memory block. Both memory blocks are required to be null-terminated. Since, in C, strings are not first-class datatypes, and are implemented as blocks of ASCII bytes in memory, strcat will effectively append one string to another given two pointers to blocks of allocated memory. The name strcat is an abbreviation of "string concatenate". strcat is found in the string.h header file.

For example:

char str1[14] = "Hello,";    /* The array has enough space for 'Hello,' plus " world!" plus a null terminator */
strcat(str1, " world!");
puts(str1);                 /* prints "Hello, world!" to stdout followed by a newline */

Here is a possible implementation of strcat:

char *
strcat(char *dest, const char *src)
    size_t i,j;
    for (i = 0; dest[i] != '\0'; i++)
    for (j = 0; src[j] != '\0'; j++)
        dest[i+j] = src[j];
    dest[i+j] = '\0';
    return dest;

It can also be defined in terms of other string library functions:

char *
strcat(char *dest, const char *src)
    strcpy(dest + strlen(dest), src);
    return dest;

Bounds errors[edit | edit source]

strcat can be dangerous because if the string to be appended is too long to fit in the destination buffer, it will overwrite adjacent memory, invoking undefined behavior. Usually the program will simply cause a segmentation fault when this occurs, but a skilled attacker can use such a buffer overflow to break into a system (see computer security).

Bounds checking variants[edit | edit source]

To prevent buffer overflows, several alternatives for strcat have been used. All of them take an extra argument which encodes the length of the destination buffer and will not write past that buffer end. All of them can still result in buffer overflows if an incorrect length is provided.

strncat[edit | edit source]

char* strncat(char* dst, const char* src, size_t n);

The most common bounded variant, strncat, only appends a specified number of bytes, plus a NULL byte. This allows each concatenated string to use no more than its "share" of a buffer and was perhaps intended to make tables. It is poorly suited to the more common need of getting the prefix of the concatenated string that fits in the buffer. For this the proper value to pass for the count is bufferSize-strlen(buffer)-1. Common mistakes are to pass bufferSize, bufferSize-1, and bufferSize-strlen(buffer), all of which can still produce a buffer overflow.

strlcat[edit | edit source]

size_t strlcat(char* dst, const char* src, size_t size);

The strlcat function, created by OpenBSD developers Todd C. Miller and Theo de Raadt, is often regarded as a safer and more useful version of strncat. It takes the actual length of the buffer as an argument, and returns the number of bytes that would be needed allowing the caller to reallocate the buffer if possible. It has been ported to a number of operating systems, but notably rejected by glibc maintainers, who suggest that C programmers need to keep track of string length and that "using this function only leads to other errors."[1]

strcat_s[edit | edit source]

errno_t strcat_s(char* dst, rsize_t size, const char* src);

The strcat_s function, proposed for standardisation in ISO/IEC TR 24731,[2][3] is supported by the Microsoft C Runtime Library.[4] and some other C libraries. It returns non-zero if the source string does not fit, and sets the buffer to the empty string (a disastrous result if the original string is not stored elsewhere or if the caller ignores the return result). It is also explicitly unsupported by some libraries, including the GLibc library.[5] Warning messages produced by Microsoft's compilers suggesting programmers change strcat and strncat to this function have been speculated by some to be a Microsoft attempt to lock developers to its platform.[6][7]

References[edit | edit source]

External links[edit | edit source]