0

I was just going through C library functions to see what I can do with them. When I came across the strcpy function the code I wrote resulted in a segmentation fault and I would like to know why. The code I wrote should be printing WorldWorld. If I understood correctly, strcpy(x,y) will copy the contents of y into x.

 main() {
    char *x = "Hello";
    char *y = "World";
    printf(strcpy(x,y));
 }
Regios
  • 23
  • 5
  • 1
    First x is pointed to a read only piece of memory. Then y is pointed to a different piece of read only memory. Then the strcpy tries to write to where x points but that location is read only. Instead you need to point x to writeable memory and initialize it with "Hello" - make x an array like this: `char x[] = "Hello";` – Jerry Jeremiah Sep 28 '17 at 01:09
  • nice explanation @JerryJeremiah . I wanted adding an answer, but i could not coin any explanation , am pretty new to c – 0.sh Sep 28 '17 at 01:11

1 Answers1

2

If it worked, the code you wrote would print "World", not "WorldWorld". Nothing is appended, strcpy overwrites data only.

Your program crashes because "Hello" and "World" are string constants. It's undefined behavior to attempt to write to a constant, and in your case this manifests as a segmentation fault. You should use char x[] = "Hello"; and char y[] = "World"; instead, which reserve memory on the stack to hold the strings, where they can be overwritten.

There are more problems with your program, though:

First, you should never pass a variable string as the first argument to printf: either use puts, or use printf("%s", string). Passing a variable as a format string prevents compilers that support type-checking printf arguments from doing that verification, and it can transform into a serious vulnerability if users can control it.

Second, you should never use strcpy. Strcpy will happily overrun buffers, which is another major security vulnerability. For instance, if you wrote:

char foo[] = "foo";
strcpy(foo, "this string is waaaaaay too long");
return;

you will cause undefined behavior, your program would crash again, and you're opening the door to other serious vulnerabilities that you can avoid by specifying the size of the destination buffer.

AFAIK, there is actually no standard C function that will decently copy strings, but the least bad one would be strlcpy, which additionally requires a size argument.

zneak
  • 134,922
  • 42
  • 253
  • 328
  • `strlcpy` ? what about `strncpy` ? – 0.sh Sep 28 '17 at 01:12
  • 1
    @0.sh, `strncpy` will not NUL-terminate the result string if it runs out of space to do so. – zneak Sep 28 '17 at 01:12
  • 1
    Apparently strlcpy is insecure as well: https://stackoverflow.com/questions/2114896/why-are-strlcpy-and-strlcat-considered-insecure – Jerry Jeremiah Sep 28 '17 at 01:12
  • Yes @JerryJeremiah, which is what I meant by "the least bad one". – zneak Sep 28 '17 at 01:13
  • 1
    Too bad my compiler doesn't come with strlcpy. Is there something portable you could recommend? – Jerry Jeremiah Sep 28 '17 at 01:14
  • @JerryJeremiah, if I knew of a better standard one, I'd have listed it here. AFAIK, there is literally no safe way to handle C strings with standard C functions, all of them mess up in a way or another, but I think that `strlcpy` is the least damaging one (short of writing on your own not-bad string routines). `sprintf(dest, dest_size, "%s", source)` does the same thing as `strlcpy`. – zneak Sep 28 '17 at 01:17