Re: Grrr
I received a number of comments on my "Grrr" post, all of which missed the point:
Yes, I am aware that there are many more ways to fix this issue beyond a memcpy. However, the example code is legal and would not crash the application, if not for the fact that libc thinks I am doing something wrong. On top of that, this kind of overflow "protection" only kicks in when the code is compiled with -O2 rather than with -g -O0. While I am not sure whether the difference is due to the absense of debugger symbols, or rather due to the different optimization levels, fact is that software which runs fine in debugging should also run fine in production.
There are good arguments for compiling all C code with -Wall -Werror, and I do that as a matter of course for all C software that I write. However, sometimes automated tools are just wrong in their compile- or run-time bug detection, in which case such it should be possible to disable that detection. This is one such case, and my blog post was more about ranting about the inability to do so, rather than about the fact that I had to memcpy when in fact there were other options available.
But yeah, perhaps I should have been clearer about that. Forgive me for not being clear after having fought with compilers for far too long.
I've had a short discussion with a PHP core developer about -Wall and that it's not used by PHP, because it would spit out tons of unhelpful stuff. I'm not literate enough in C to have any opinion on this. But I have a strong feeling, that you should either use -Wall or work out the issues with the gcc developers. Would you mind pointing me to some informations regarding the pros and cons of -Wall or giving me your arguments? Thanks a lot!
Except your code isn't legal under the C standard. The C standard is perfectly clear: pointer arithmetic on a pointer to array object must result in a pointer that points to an element of the array object or the "one past the end" element of the array object. In the latter case, you're not allowed to deference the resulting pointer.
The moment you do anything else, you're instantly in undefined behavior land. It doesn't matter that the array is in a struct so there must be extra bytes there. It doesn't matter you've used a compiler-specific directive to kill padding. You overran the array 'str' sothe compiler is allowed to do anything it wants with your code, including shoot demons out your nose.
Nothing in the C standard promises the ability to allow a pointer to cross from one object to another (even if the happen to be adjacent), nor does GCC make such a promise anywhere, either. You must assume that all objects are by themselves in a sea of memory, even when you know this not to be the case.