2

Almost any question on undefined behavior elicits an answer saying that "undefined behavior may time travel" and/or that "the presence of undefined behavior makes the entire program undefined".

In the simplified example from this question, UB is said to enable the compiler to eliminate the else branch altogether, optimizing

void foo(int* p)
{
    if ( p ) {
        bar();
    } else {
        baz();
        *p = 1;
    }
}

to

void foo(int* p)
{
    bar();
}

But what if baz() contains an observable operation (I/O) or throws an exception?

Even though the C++ Standard places no requirement on the implementation executing a program which would result in undefined behavior (not even with regard to operations preceding the first undefined operation), a standard-compliant non-malicious compiler should not take advantage of that provision by injecting artificial calls to nasal demons as soon as it detects a possibility of UB. The most that the compiler can do about UB is to assume that it doesn't happen and optimize accordingly.

If we only consider such compilers, what are the barriers that should stop the propagation of UB?

Community
  • 1
  • 1
Leon
  • 31,443
  • 4
  • 72
  • 97
  • You are asking for [volatile variables](http://stackoverflow.com/questions/4437527/why-do-we-use-volatile-keyword-in-c) – amchacon Nov 12 '16 at 12:35
  • 2
    the thing is, if your program invokes undefined behaviour at any point, it is already ill formed, so it is not valid program in C and/or C++, depending which you are coding at that point. So the compiler can do as it please, because it can assume that no valid program will have any undefined behaviour in it, and if it does, the compiler doesnt need to fear, because the program is not valid anyways. Obviously UB will not do something like disk formatting, but it can have some consequences for the program itself(for instance seg faulting). Good talk about UB: https://youtu.be/yG1OZ69H_-o – Creris Nov 12 '16 at 12:43
  • 1
    @Creris if your UB leads to remote code execution then with the input data crafted for this situation, it may very well lead to disk formatting. Or privilege escalation to the level allowing that ;) – krzaq Nov 12 '16 at 12:50
  • @amchacon do they actually help in cases like this? – harold Nov 12 '16 at 13:52
  • @harold well, he is asking for *observable operations*. I am thinking that P pointer could be changed from outside. – amchacon Nov 12 '16 at 13:54
  • @amchacon how? `baz` doesn't take `p`'s address. I think the point was that `baz` can go and, say, print something to the console (and then, presumably, die with a access violation) but due to UB *later* it can still be assumed unreachable and thus never print in the first place. – harold Nov 12 '16 at 13:57
  • @krzaq yes of course, but more often than not you do not have piece of code that tries to remotely execute something and has UB, most often you have UB of type "off by one", or null deref or something like that, which still can have tragic endings(Heartbleed) but surely less severe than remote execution, possibly with elevated privileges – Creris Nov 12 '16 at 14:11
  • @Creris Well, the wording I usually see is that it *can* happen, not that it *must*. You're right, of course, that a lot of conditions must be met to allow code execution. – krzaq Nov 12 '16 at 14:14
  • @Creris: The question, I think, is whether a compiler must consider the possibility that a platform might *define* the behavior of reading some particular external volatile variable as stalling the CPU until something happens. The fact that code *would* invoke UB if the event occurred should not affect the code's behavior if the event in question does not actually occur. – supercat Nov 15 '16 at 15:03
  • @supercat well there is still the point that if any part of your program contains UB your whole program is ill formed, so it doesnt even matter if you ever invoke it or it happens, the compiler can already assume the code is not valid and do whatever transformation it seems fit(probably as part of optimizing) – Creris Nov 15 '16 at 18:11
  • 1
    @Creris: The fact that a program would produce UB with some inputs does not in any way affect behavior when it is not given those inputs. Perhaps the fundamental question is whether the ability or inability of code to continue execution following a volatile access to an external variable the compiler knows nothing about is considered an "input". If it is, and the volatile access prevents further code execution, then the program will not have received input that would allow further code to execute; even if succeeding code would trigger UB, the fact that the program didn't receive input... – supercat Nov 15 '16 at 18:26
  • ...that allowed it to execute would imply that behavior should remain defined. – supercat Nov 15 '16 at 18:27

0 Answers0