Reputation: 11
I was expecting a segfault with this code:
char * foo (char my_ascii[10])
{
strcpy (my_ascii, "0123456789");
return my_ascii;
}
char bar[2];
printf("%s\n", foo (bar));
Because bar reserves a 2-char array in the stack, and foo() tries to write 10 chars. However, printf() writes in stdout 10 chars and errors don't occur. Why is this happening?
Additionally, if I modify the foo() function this way:
char * foo (char my_ascii[1])
{
strcpy (my_ascii, "0123456789");
return my_ascii;
}
The behaviour is exactly the same: 10 chars are copied to my_ascii. Any explanation?
Thank you very much in advance.
Upvotes: 1
Views: 210
Reputation: 64682
It is true that bar
has reserved 2 characters, and you're filling it with 8 more characters than it can handle.
That doesn't automatically mean seg-fault.
You don't know what is in those over-flowed 8 characters, and it is likely meaningless garbage that is safe to overwrite. The seg-fault will happen when you actually overwrite into another page of Virtual Memory, or overwrite something important (like a device driver, or program code).
This is a good example of undefined behavior. Undefined doesn't mean it WILL fail, it really means that the behavior is undefined; it might work, it might fail, monkeys may fly out of the USB port... anything could happen. In this case, it actually works, but you cannot rely on that behavior, because it might be different the next time you run the program.
And finally, just because there isn't an immediate failure, it doesn't mean you didn't damage the system. You might've screwed up memory with your overwrite, and you may not see it until much further in your program, when it suddenly crashes on completely normal code that happened to rely on the same area of memory.
BTW: There's another bug in your code.
You describe my_ascii
as 10 characters, but you try to copy 11 chars into it.
Don't forget about the NULL-terminator at the end of strings!
This means the string "0123456789"
actually requires 11 characters of storage.
Upvotes: 0
Reputation: 116266
Specifying the length of the array parameter like
char * foo (char my_ascii[1]) ...
does not make any difference, as it is omitted (the array decays into a pointer inside the function).
Moreover, buffer overflow is undefined behaviour, which means just that: there is no guarantee that the program will crash. It may perfectly legally look as if there were no problem... or generate a segfault only on Thursdays when there is a full moon... or silently delete all records from your DB. Really, anything.
Upvotes: 2
Reputation: 92864
char * foo (char my_ascii[10])
and char * foo (char my_ascii[1])
are both equivalent to char * foo (char *my_ascii)
Note: An array type decays into a pointer(to the first element of the array) type when passed to a function.
Because
bar
reserves a 2-char array in the stack, andfoo()
tries to write 10 chars. However,printf()
writes in stdout 10 chars and errors don't occur. Why is this happening?
That's because undefined behaviour means anything can happen.
Just for the record
Undefined Behavior means behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
NOTE: Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
Upvotes: 1
Reputation: 108938
First, these definitions are absolutely identical:
char *foo1(char arr[10]) { /* ... */ }
char *foo2(char arr[1]) { /* ... */ }
char *foo3(char arr[]) { /* ... */ }
char *foo4(char *arr) { /* ... */ }
Second, writing outside the limits of an object is Undefined Behaviour. Anything can happen! If you're lucky, your test run will crash and you will make it right; if you're not so lucky, your test run will work as you expect only to fail when you demo it to the client (or your boss).
Upvotes: 1
Reputation: 91270
Unfortunately, undefined behavior means anything can happen - including no symptoms of the error. In this case, you overwrote a part of stack, but it didn't affect anything.
Upvotes: 0