Re:Defining the Undefinedness of C (2015) [pdf]
by iainmerrick on Wednesday July 26, 2017 @12:49PM
(#14857868)
That code ought to be a compile error. "On this code path, your code assumes ptr is null and not-null at the same time!"
Not all UB can be detected at compile time, but when it can be detected, it should be flagged to the user.
Re:Defining the Undefinedness of C (2015) [pdf]
by simias on Wednesday July 26, 2017 @01:00PM
(#14857974)
But what if it's the result of some inlining or simply macro expansion? It's a tough call to make.
Re:Defining the Undefinedness of C (2015) [pdf]
by inetknght on Wednesday July 26, 2017 @01:37PM
(#14858299)
If it's from inlining, then the compiler has a bug. If it's from a macro, then stop using macros in a broken fashion. Let it be an error.
Re:Defining the Undefinedness of C (2015) [pdf]
by jjnoakes on Wednesday July 26, 2017 @04:02PM
(#14859728)
How would that be a compiler bug? Assuming g() is never called with a NULL pointer, this code should not produce any compile-time errors:
int f(int *x)
{
if (x == NULL) return 0;
return *x;
}
int g(int *p)
{
return (*p) + f(p);
}
Re:Defining the Undefinedness of C (2015) [pdf]
by kbenson on Wednesday July 26, 2017 @02:19PM
(#14858720)
This is essentially what caused the Cap'n'Proto remote vulnerability[1] 6 months back. The compiler optimized away an overflow check that directed control to an error handling path, eliding the code that checked for the exact error. Fun.
This is a very simple example of course, but maybe this "increment" code is actually used in many other parts of the codebase where the test actually makes sense.
It's not rare for instance to start a C function with "if (param == NULL) return;", just in case. If the compiler inlines the function and sees that the caller dereferences "param" it can assume that it's not null and remove the test.
But you're right that it makes it easy to shoot yourself in the foot. I remember a strange bug in the linux kernel source that was "hidden" by such an optimization, the code looked something like that:
The real code was a little more complicated than that obviously, but at a glance it might look that the function won't run if "ptr" is NULL. GCC however noticed the dereference before the test and happily decided that "of course this coder knows what they're doing, ptr can't be NULL!" and removed it.It can take a while to debug code like that.