-4

The strcpy function works weirdly and I want to know what is happening.

char name[] = "The Batman"; //10 characters
char name2[5];

strcpy(name2, name);

name is now changed for some reason. It is now "atman". Why is name changing over here? name2 however is successfully been assigned to "The batman". How is it possible since name2 isn't large enough to hold "The Batman".

Retired Ninja
  • 4,785
  • 3
  • 25
  • 35
  • 1
    You wrote outside the bounds of the allocated array and corrupted something else. In many cases this will cause the program to crash. – Retired Ninja Aug 21 '23 at 04:43
  • 1
    Look at the documentation for strcpy()`: https://man7.org/linux/man-pages/man3/strcpy.3.html. You made several errors: 1) the size of array "name[]" is actually *11 bytes*: 10 char + null delimiter. 2) copying (10 character) "name" to (5 byte) "name2" will *OVERWRITE* memory: [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior). This is Bad. Very Bad. Consider [strncpy()](https://man7.org/linux/man-pages/man3/strncpy.3p.html). – paulsm4 Aug 21 '23 at 04:47
  • C doesn't protect you from your mistakes — you have to know what you're doing, and you have to make sure there's enough memory available in the target area when you copy strings around. – Jonathan Leffler Aug 21 '23 at 04:49
  • What am I corrupting? My code contains nothing more than this. Also mine isn't crashing which would have made sense instead of name2 being assigned correctly. – Sudipta Sarker Aug 21 '23 at 04:49
  • 3
    Dude - just because it doesn't happen to crash on your particular app... *DOESN'T* mean it's "correct" ... or "safe". The insidious thing about buffer overflows is that, by corrupting internal data ... they can cause failure at a LATER time, in a DIFFERENT part of the program. For example, you can inadvertently trash an I/O stream... and you might not notice any problems until you later try to read, write or close the stream. – paulsm4 Aug 21 '23 at 04:55
  • 1
    "What am I corrupting?" "Why is name changing over here?" Do you see the contradiction? – Retired Ninja Aug 21 '23 at 05:09
  • _What am I corrupting?_ You're corrupting `name` — as it happens. There's no guarantee that the arrays will be laid out so that the overwriting modifies `name`; it could modify the call stack instead, leading to crashes. Or anything could happen — because copying beyond the limits of the arrays is undefined behaviour. There is no information provided to `strcpy()` to let it know how big `name2` is, so it can't prevent overwriting. You have to do that as the programmer. C does not babysit you — it does not protect you from your mistakes. – Jonathan Leffler Aug 21 '23 at 05:45
  • _How is it possible?_ It is possible precisely because `name2` isn't large enough to hold "The Batman". – Jonathan Leffler Aug 21 '23 at 05:47

1 Answers1

1

Before strcpy:

name2 [ ] [ ] [ ] [ ] [ ]
name  [T] [h] [e] [ ] [B] [a] [t] [m] [a] [n] [\0]

After strcpy:

name2 [T] [h] [e] [ ] [B]
name  [a] [t] [m] [a] [n] [\0] [t] [m] [a] [n] [\0]

i.e. the strcpy overrun the memory allocated by name2 onto the start of name rewriting the contents at the start.

Of course, when you print name, the print will stop at \0 and will only show "atman".

When you print name2 it will exceed the 5 characters you assigned and overrun into name memory and show you (what you believe is correct) "The Batman", but, it is already indicating something is wrong in that you can see a string stored there that's larger than the memory you allocated.

You are lucky your programming didn't crash.

The code that you provided is actually unpredictable behavior because there is no guarantee that compilers will organize name and name2 as I depicted above. In fact, had name2 been organized last, the strcpy may have violated all sorts of other variables and/or code.

Nowadays, C strcpy is regarded to be quite unsafe. Modern compilers warn you against calling it directly. They will try to coerce you to use strncpy instead.

Stephen Quan
  • 21,481
  • 4
  • 88
  • 75
  • 3
    `strncpy` has its own problems (not properly null-terminating the string if it is too long), so some OSes have added the non-standard `strlcpy` to actually work properly and do the right thing. – Chris Dodd Aug 21 '23 at 04:59
  • So if I am getting it right, since the destination is not large enough, what can be copied is copied into destination and the rest is being copied to the source. – Sudipta Sarker Aug 21 '23 at 04:59
  • @SudiptaSarker the `name`, `name2` and `strcpy` has no range validation, so, it will blindly copy everything and will only stop when it sees the `\0`. – Stephen Quan Aug 21 '23 at 05:01
  • 2
    strcpy() *CAN* be safely used... if you're careful. Similarly, strncpy() has some dangerous pitfalls. For example, `strncpy(name2, name, 5)` will *FAIL* to copy a terminating byte to "name" :( – paulsm4 Aug 21 '23 at 05:02
  • And the other interesting behaviour of `strncpy()` is that `char buffer[1024]; strncpy(buffer, sizeof(buffer), "abc");` will copy 1020 extra null bytes to `buffer`. That can be expensive if you're building up a big string from bits and pieces using `strncpy()`. And don't even think of using `strncat()` if you value your sanity. – Jonathan Leffler Aug 21 '23 at 05:50