Protecting the world

from criminally bad code

strcpy

Synopsis

#include <string.h>

char* strcpy(char* restrict s1,const char* restrict s2);

Description

strcpy copies a null-terminated string from one location to another.

Pitfalls

Destination buffer overflow

The strcpy function has no knowledge of the size of the destination buffer, therefore cannot and does not prevent that buffer from overflowing if it is too small.

This is a particularly serious hazard because it can sometimes be deliberately induced by presenting a suitably-crafted string of characters to the program. This is called a buffer overflow attack, and it has the potential to allow arbitrary code execution.

Buffer overflows can be avoided:

  • by using a function to perform the copying that takes account of the buffer length, or
  • by ensuring that the buffer is large enough to accommodate the copied string before strcpy is called.

The first method is usually considered preferable to the second because of the difficulty of reliably verifying that all calls to strcpy have been made safe.

Overlapping source and destination buffers

The behaviour of strcpy is undefined if the source and destination strings overlap[1]. If there is a risk of this happening then the best alternative is likely to be using strlen in combination with memmove, as described below.

Alternatives

Using strncpy

As its name suggests, strncpy copies a string into a buffer of a specified length:

char s1[256];
strncpy(s1,s2,sizeof(s1));

Unfortunately it has two significant drawbacks: it pads the buffer with zeros (which is usually unnecessary), and in the event of an overflow it does not terminate the buffer.

Using snprintf

Although it is not intended for the purpose, snprintf can be used as a safe alternative to strcpy that does not have the idiosyncratic behaviour of strncpy:

char s1[256];
snprintf(s1,sizeof(s1),"%s",s2);

Its main drawback as compared to strcpy is the time taken to parse the format string, which can have a serious adverse effect on performance when there are many short string to be copied.

Using strlen and memmove

The standard library does not provide a strmove function analogous to memmove, so it is necessary to improvise if there is a risk that the source and destination strings might overlap. One way to do this is by using strlen and memmove:

  1. Measure the length of the string to be copied using strlen,
  2. Add one to accommodate the terminating null, then
  3. Copy the string to its intended destination using memmove.
char* strmove(char* s1,const char* s2) {
    size_t n=strlen(s2);
    memmove(s1,s2,n+1);
    return s1;
}

(A similar method can be used to write a function equivalent to strncpy that is usable when s1 and s2 overlap.)

Portability

  •  C90
  •  C99
  •  C++98
  •  C++11

In C++, use of the header <string.h> is deprecated in favour of <cstring>.

Notes

  • [1] C99 §7.21.2.3 ¶2

Further reading

  • The strcpy function, Programming languages — C, ISO/IEC 9899:1999, §7.21.2.3, p325
  • strcpy, The Open Group Base Specifications, Issue 7, The Open Group, 2008
  • strcpy(3), Linux Programmer’s Manual, The Linux man-pages project
  • Copying and Concatenation, The GNU C Library Reference Manual, The GNU Project