strcpy(3)

C library function

Copies a string, null byte included, into a buffer you provide. strcpy ignores the size of the destination: guaranteeing it is your job.

Synopsis
#include <string.h>
char *strcpy(char *restrict dst, const char *restrict src);

Description

strcpy copies the string src, final null byte included, into the array dst. The argument order is the one of an assignment: destination first, dst = src. The function receives no size: it copies up to the '\0' of the source, however much room there is. The destination must therefore offer at least strlen(src) + 1 bytes, and checking that is the caller's job.

Return value

dst, the pointer it received. No error is ever reported: a destination that is too small or a src without a terminator goes undetected, and both are undefined behavior.

Pitfalls

The overflow is silent. In the example below, 13 bytes are copied into an array of 8, and the program prints the full name and exits normally. The 5 extra bytes overwrote whatever followed name on the stack. Nothing guarantees it will go this smoothly anywhere else.

When you compile with -O2 -D_FORTIFY_SOURCE=2, glibc replaces the call with a version that knows the size of dst when the compiler can see it, and stops the program instead of overflowing. Handy during development, but this safety net does not replace the check.

When you allocate the copy yourself, do not forget the null byte: malloc(strlen(src)) is one byte short, malloc(strlen(src) + 1) is right. strdup(3) does both steps in one call.

If src and dst overlap, for example to shift a string inside its own array, the behavior is undefined. Use memmove(3).

dst must be writable: char *dst = "text"; points to a read-only string literal, and copying into it usually crashes. Declare an array.

For a bounded copy, strncpy(3) is the wrong answer, because it can leave the destination without a null byte. Check the length with strlen(3) before you copy, or use snprintf(dst, sizeof dst, "%s", src), which truncates cleanly when dst is an array.

Example

hello.c
#include <stdio.h>#include <string.h>
int main(int argc, char **argv){    char name[8];
    if (argc != 2)        return 1;    strcpy(name, argv[1]);    printf("Hello %s\n", name);    return 0;}
Terminal
$ gcc -Wall -Wextra hello.c -o hello$ ./hello AdaHello Ada$ ./hello "Ada Lovelace"Hello Ada Lovelace$ gcc -Wall -Wextra -O2 -D_FORTIFY_SOURCE=2 hello.c -o hello-fortify$ ./hello-fortify "Ada Lovelace"*** buffer overflow detected ***: terminatedAborted

"Ada" takes 4 bytes with its '\0', so the copy fits. "Ada Lovelace" takes 13 for 8 available: the first build overflows without a word, the fortified build stops dead on buffer overflow detected.

C

strcpy

Write gm_strcpy, which copies src into dst one character at a time, the final null byte included, and returns dst.

Open the exercise

Now write it yourself.