AlvaroBegue wrote:bob wrote:AlvaroBegue wrote:I am confused by the statement "Not one single instance of strcpy() will break on the example I gave where you do strcpy(st, st+n)." Isn't this whole thread about an instance where it did break?
It broke because Apple broke it. Apple introduced a check for overlapping source and destination and aborted if it was detected. Code works perfectly.
I consider that a courtesy. Of course it would be better if they could give you a meaningful error message about it. But aborting is better than doing what you expect it to do.
`strcpy(st, st+n)' can certainly do things you don't expect, even if the compiler isn't breaking things on purpose:
http://stackoverflow.com/questions/1293 ... mplemented
EDIT: Here's how other people handled the situation:
https://lists.gnu.org/archive/html/bug- ... 00014.html
This will be fixed in the next release of [...]
That's how one should react to things like this happening.
You are simply not reading what I have written. Let me try once more. There is ABSOLUTELY no way my use of strcpy() will break.
Here is the basic call:
strcpy(a, a+n);
First, a is a properly formatted string with a terminating null. Guaranteed, because I read the stuff in and add the null in the correct place.
Second, n < strlen(a), which means that a+n (where n is just an integer offset) is guaranteed to point to a character before the terminating null, or the terminating null itself. Hence no buffer overrun is possible.
finally, since the two strings use the same character array, I know that the array is long enough to hold the original string (it already does, and it has been properly verified to be no longer than the array, as any good programmer would do), which means it is also long enough to hold the right-most end of that same string since that is shorter than the original.
An example:
char buf[4096];
Buf is initialized to "abc def ghi jkl" which is a 16 character string with the terminating null on the end.
strcpy(a, a+4);
simply converts that string to "def ghi jkl" with the terminating null still in place.
Before the copy, strlen(a) == 15;
n=4 (n < 15)
After the copy, strlen(a)=11;
There is nothing that can break that so long as it is copied left-to-right. Absolutely nothing. n can never be negative, and in fact can not even be zero in my code.
Again, as I have stated MANY times, the above will never misbehave unless someone decides to copy right to left. But with a null-terminated string that is not likely to happen as it is slower.
In the case of Apple, they had to do two bad things. 1. Search for the null and then use that to determine if the strings overlap. Slows things down unnecessarily; and 2, simply print "Abort" with no explanation or anything.
Undefined behavior is not always bad. I know what I am doing when I use integer overflow. I know what I am doing when I choose to allow a parallel race condition. I don't need the compiler to jump in and break the code intentionally. If Apple had simply broken race conditions rather than strcpy() more would be complaining because everyone deals with races on the hash stores. As opposed to locking before writing which is a performance killer with no significant gain.
The link you gave is a classic example of what I consider to be bad behavior. How many things did they break just to make some sort of pedantic stand on undefined behavior means crashing is as acceptable as doing the right thing?
Another point that neither you nor anyone else has addressed...
once you know the strings overlap, why not just call memmove() from within strcpy()? In fact, since they are looking specifically to see if they overlap, why not just change strcpy to this:
memmove(st1, st2, strlen(st2)+1);
and be done with it? Now nothing is broken, the undefined behavior is gone, everybody is happy, no bugs get reported. How is that worse than just changing well-established behavior to become "crash"????