...
- to give the implementor license not to catch certain program errors that are difficult to diagnose
- to avoid defining obscure corner cases which would favor one implementation strategy over another
- to identify areas of possible conforming language extension: the implementor may augment the language by providing a definition of the officially undefined behavior
Conforming implementations can deal with undefined behavior in a variety of fashions, such as ignoring the situation completely, with unpredictable results; translating or executing the program in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message); or terminating a translation or execution (with the issuance of a diagnostic message). Because compilers are not obligated to generate code for undefined behavior, these behaviors are candidates for optimization. By assuming that undefined behaviors will not occur, compilers can generate code with better performance characteristics.Unfortunately,
Increasingly, compiler writers are taking advantage of undefined behaviors do occur, particularly in the presence of an attacker. Optimizations make it difficult to determine how these systems will behave in the presence of undefined behaviors. This is particularly true when visually inspecting source code that relies on undefined behaviors; a code reviewer cannot be certain if the code will be compiled or if it will be optimized out. Furthermore, just because a compiler currently generates object code for an undefined behavior does not mean that future versions of the compiler are obligated to do the same; the behavior may be viewed as an opportunity for further optimization. Compilers are also not required to issue diagnostics for undefined behavior, so there is frequently no easy way to identify undefined behavior in codeC programming languages to improve optimizations. Frequently, these optimizations are interfering with the ability of developers to perform cause-effect analysis on their source code, that is, analyzing the dependence of downstream results on prior results. Consequently, these optimizations are eliminating causality in software and are increasing the probability of software faults, defects, and vulnerabilities.
All of this puts the onus on the programmer to write strictly conforming codedevelop code that is free from undefined behaviors, with or without the help of the compiler. Because performance is a primary emphasis of the C language, this situation is likely to get worse before it gets better.
Noncompliant Code Example
...