7 ms·
Why do we need for an Undefined Behavior Annex to C++
- deleted 3y ago[deleted]
- planede 3y agoGreat stuff. It looks like a ton of upfront work, but will greatly improve the standard, and shouldn't be too hard to maintain once it's complete.
- mike_hock 3y agoOnce it's complete, make it authoritative. Any mention of undefined behavior should be required to reference the corresponding item in the UB annex.
- marcosdumay 3y agoAnd even better, start reducing the list after it's complete, by pushing things like integer overflow into implementation defined; several uses of inc/decrement operators into compilation error; and etc.
- bluGill 3y agoI don't want integer overflow to be implementation defined though, I want it undefined so my compiler can optimize my code for the fact that I don't overflow my integers in the first place.
- SAI_Peregrinus 3y agoThe implementation can define the behavior on overflow to be the optimized behavior. Optimization and UB are orthogonal concepts.
- planede 3y agoImplementation defined is not much better than undefined. It only requires documenting the behavior, so compilers could just go like "here are all the optimizations that we apply on each target platform for each set of compiler flags". It's not very helpful, you might as well look at the source code of the compiler.
- SAI_Peregrinus 3y agoThat's still substantially better than undefined, where multiple runs of the same compiler version on the same source with the same settings are allowed to result in different behaviors. I suppose an implementation could define non-deterministic behavior, but that's unlikely and could be forbidden by the standard. That said, my overall point is that optimization does not rely on undefined behavior at all. It's commonly argued that it does, but there are languages without undefined behavior that have working optimizers, so it's clearly false. Some optimizations for C (and C++) currently depend on undefined behavior, but there's nothing inherent about that dependence.
- nlewycky 3y agoThe hard part of UB isn't where it's mentioned in the standard. The problem is when the standard says "in case A, X occurs, in case B, Y occurs" then somebody invents a situation where neither A nor B apply.
- SunlitCat 3y agoI know, the goal is (in short) a listing of expected undefined behavior, which could improve security if developers follow along. But isn't putting undefined behavior into the standard an oxymoron, kinda?
- mike_hock 3y agoNo, because UB is not avoidable in principle unless you create a walled garden/sandbox that must be enforced at non-zero runtime cost.
- vlovich123 3y agoI don’t know. Safe rust has 0 UB although if I recall correctly things are still a bit messy with integer overflow. I could imagine a world where we define annotations around “signed integer will never overflow” that you can add to hit paths but otherwise disallow optimizing around that UB and for all other UB require an explicit annotation acknowledging it or just a warning and a missed optimization instead. The current status quo is not the best.
- aw1621107 3y agoThe key is "that must be enforced at non-zero runtime cost." Safe Rust is indeed generally free of UB, but that requires bounds checks at a minimum. > I could imagine a world where we define annotations around “signed integer will never overflow” that you can add to hit paths but otherwise disallow optimizing around that UB That's kind of what Rust does - overflow is not UB, but you can use unchecked_add/mul/div/sub to get UB-on-overflow if you explicitly want it.
- jeffbee 3y agoHow does Rust as a language avoid the "UB" traps that are fundamentally just compiler optimizations? For example in the case where you have an array of 8 elements, you access the element at index x, then (in program order) test whether x is less than 8. It seems than an optimizing compiler with a known-bits analysis could conclude that x is always less than 8, and remove that test. I don't know much about languages, so I am interested in how that trap is a consequence of C and avoided by Rust.
- j16sdiz 3y ago> We also will require future proposal authors to keep the annex updated if they add or remove undefined behavior. They are making undefined behavior an explicit topic to be discussed when reviewing a proposal. This is great.
- wahern 3y agoNotably, the C standard does have an undefined behavior annex, Annex J.2, since C99. It's not mentioned in the post, and this omission in tandem with repeated usage of "C and C++" at various points might suggest otherwise to some people.
- quelsolaar 3y agoAnd C has a UB study group and we are working on a technical rapport that in great detail describes how UB works in C, and a comprehensive list of sample code for all known UB.
- tux3 3y agoIs there hope that we could some day achieve an exhaustive lists of all undefined behavior that C programmers need to be aware of? I realize no one really knows today, but is there a path?
- trws 3y agoNo. It would require listing not just every place the standard states undefined behavior is the result, but also every corner case not covered by the spec, or that is under-specified. It’s possible to document known instances, but never to document all possible sources of undefined or unspecified behavior.
- quelsolaar 3y agoThw C standard has a list of all known UBs. We don't know if the list is complete, because the C standard makes anything not defined by omission UB, so its possible to discover new UB. The language is however pretty thoroughly explored.
- jurschreuder 3y agoI love how in C++ there seems to be this security issue, and now hundreds of people try to come up with different ways on how to tackle the problem. Everybody wants to help and spend their free time on it. You don't see this in other languages so much. People just use those languages and "they" have to fix any flaws. Also keep your bingo cards ready for people saying Rust does not have undefined behaviour. I'm also not so sure Rust is even that safe. Yes it's memory safe but the languages with the most vulnerabilities is not C++. It's PHP, .NET, C, Java, JavaScript. C++ is not an unsafe language. You can't make a language safe by adding an "unsafe" keyword end expect everything outside it to be safe. Else .NET and Java would be lower on the list than C++ because they do have bounds checks and they don't have raw pointers. It's a bit of a false sense of security and a play of words this "unsafe" keyword in Rust.
- theragra 3y agoYou have data to confirm your claims? Moreover, vulnerabilities in languages themselves are not that important in comparison to vulnerabilities in software written in the specific language, at least how I understand this.
- wbkang 3y agoI don't have solid data but for "core" mature software written in c/c++ like browsers and Linux, I feel like I see far more high profile security bugs from the lack of memory safety rather than something like "Linux failed to enforce the existing permissions".
- n2d4 3y ago> You don't see this in other languages so much. People just use those languages and "they" have to fix any flaws. You absolutely do see that elsewhere, and that's why here on HN we have a different new JS framework every day. The safety in Rust (and .NET, and Java) doesn't come from the `unsafe` keyword, it comes from the guarantees that you have when you don't use said keyword. Ownership, garbage collectors, and less undefined behaviour are some reasons why those languages are considered safer. At the end, memory safety is a spectrum, and while you can still break Rust's (or even Java's) memory model, it's much harder to do so unintentionally. That's a win. Even if there are some undefined edge cases!
- urbandw311er 3y agoCan we fix the post title? We don’t “need for” things, we “need” things.