8 ms·
Taming the UB Monsters in C++
- roca 2y agoThere isn't anything new here to defend against lifetime-related UB. For that it simply references https://arxiv.org/pdf/2503.21145 https://arxiv.org/pdf/2503.21145, which is just a summary of existing dynamic mitigations --- which don't fix UB at the language level, impose performance tradeoffs, and in the case of pointer integrity, require hardware support that excludes e.g. x86. Look at it this way --- mature products like Chrome are already doing all of that wherever they can. If it was enough, they wouldn't worry about C++ UB anymore. But they do.
- Voultapher 2y agoAt this point I'm wondering if C++ leadership is either willfully ignorant or genuinely in denial. I know several people on various C++ committees and by and large their opinion is, we evolve the language and library to give existing projects incremental improvements without asking them to rewrite them, but if you are starting with a new project C++ is often a subpar option. From that perspective I get why they'd be hesitant about efforts like Circle. Circle and co. ask developers to rewrite their code, in something that looks very different to normal C++ - whatever normal C++ even is, given the multitude of dialects out there - can't seamlessly interop with existing code, needs a new incompatible standard library, that as of now doesn't even exist. At which point, honestly just rewrite it in Rust instead of going through the painful exercise to use something that's 10+ years behind where Rust is today in terms of DX, tooling and ecosystem. But all that doesn't explain why at the very top, even mentioning Rust as an alternative seems taboo, idk.
- pjmlp 2y agoThere is also a strange dynamic going, and this has worked against C++. In the early ISO days, the people sent to ISO were employees from compiler vendors, and existing practice was the key factor into adding stuff to the standard. Eventually, comitee dynamics took place, and nowadays most of the contributors to WG21, and to lesser extent WG14 (which still keeps more close to the existing practice spirit), you have hundreds of contributors wanting to leave their historical mark on the ISO standard, withough having written a single line of compiler code, validating their proposal, which they are able to fight trough the whole voting process, and then leave the compiler vendors sorting out the mess how to implement their beloved feature. Those of us that really like C++, are also kind of lost on how things turned out this way.
- stingraycharles 2y agoWell, you kind of have your answer right there: it’s a language designed by committee, not by “the industry”. This has been my biggest problem, and I say this as someone who has been on and off developing C++ for over 2 decades. At the same time, it’s a safe bet to say that C++ will still be around in another 2 decades.
- pjmlp 2y agoDon't forget that same applies to C.
- gpderetta 2y agoProof of implementation should be a requirement for every proposal (allegedly it is, but in practice...). Which would limit most "outsider" proposals mostly to library features, which would be a good thing I guess.
- jcranmer 2y agoWG21 is well down the path of actively being hostile to the implementers of C++. There was a recent proposal where all 4 implementers [1] stood up and said "no", and the committee still voted it in, ignoring their feedback. [1] C++ has only 4 implementations these days, Clang, EDG, GCC, and MSVC; everything keeping up with the standard is a fork of one of these projects.
- zombot 2y ago> even mentioning Rust as an alternative seems taboo, idk. Rust is even framed as an "attack on C++" by Stroustrup himself [1]. No wonder it's taboo. [1] https://www.theregister.com/2025/03/02/c_creator_calls_for_action/ https://www.theregister.com/2025/03/02/c_creator_calls_for_a...
- unboundedjiure 2y agoSeems like a bit of a sensationalist deduction from what looks like a pretty levelheaded response. It's not a call to war, but call to improve the C++ standard
- steveklabnik 2y agoThe Register article was written based on a leaked paper, since then, Bjarne published the article itself, which you can read here: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3651r0.pdf https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p36... Not trying to take a position about if it's sensational or not, just wanting to add a primary source here.
- pron 2y agoC++ developers worry about all UB, but we don't worry about all of them to the same extent. MITRE's CWE Top 25 [1] lists out-of-bounds write as the second most dangerous weakness, out-of-bounds read as the sixth, and use after free as number eight (null-pointer dereference and integer overflow are at nos. 21 and 23 respectively). All UBs are worrisome, but that's not to say they are equally so. Taking care of out-of-bounds is easier than UAF and at the same time more important. Priorities matter. [1]: https://cwe.mitre.org/top25/archive/2024/2024_cwe_top25.html https://cwe.mitre.org/top25/archive/2024/2024_cwe_top25.html
- roca 2y agoI don't know where that ranking comes from. It also matters that attackers adapt: UAF exploitation is harder than out of bounds, but it is well understood, and attackers can switch to it, so shutting off one source of UB isn't as effective in practice as you might expect.
- pron 2y ago> I don't know where that ranking comes from. It comes from MITRE (https://en.wikipedia.org/wiki/Mitre_Corporation https://en.wikipedia.org/wiki/Mitre_Corporation), and the methodology is explained on the website (roughly, the score is relative prevalence times relative average vulnerability severity). > and attackers can switch to it, so shutting off one source of UB isn't as effective in practice as you might expect. If that's how things work, you could say the same about all the other weaknesses that have nothing to do with UB.
- Wumpnot 2y agoInteresting, for all the winging about C or C++ this shows most of these apply to all languages, and the ones that relate to C or C++ are actually pretty easy to prevent in C++(less so in C) by enabling hardening modes and using smart pointers.
- pron 2y agoBecause these are ranked by prevalence x severity, and most programs are written in memory-safe languages, the UB-related weaknesses are probably at the top of the list for programs written in C or C++, especially because "ordinary" servers are usually not written in those languages. But the point is that, indeed, even within these unsafe languages, not all kinds of unsafety are equal. It is true to say that memory-safety issues are among the biggest problems in C and C++, but it is not true to say that unless you absolutely prevent them all you remain in the same spot. If you significantly reduce or prevent some of the memory safety issues, you're in a place that's not too different from that of programs in memory-safe languages.
- techbrovanguard 2y ago> Tech pundits still seem to commonly assume that UB is so fundamentally entangled in C++’s specification and programs that C++ will never be able to address enough UB to really matter. - denial ← you are here - anger - bargaining - depression - acceptance Cope, seethe, mald, etc.
- kookamamie 2y agoAt depression they'll figure out the codebase is full of const-casts and null-dereferences. I completely agree this is trying to polish a turd, essentially. The train has left the station some decades ago.
- steve_gh 2y agoBut you are never going to rewrite the gazillion or so lines of C++ out there, and currently being used in all sorts of production systems. But if you have a beter compiler that points out more of the problem UB areas in your codebase, then you have somewhere you can make a start towards reducing the issues and attack surface. The perfect is often the enemy of the good. (edit - typo)
- lambdaone 2y agoI don't doubt that most of the gazillion of so lines of legacy C++ will never be rewritten. But critical infrastructure - and there's a lot of it - most certainly needs to be either rewritten in safer languages, or somehow proved correct, and starting new projects in C++ just seems to me to be an unwise move when there are mature safer alternatives like Rust. Human civilization is now so totally dependent on fragile, buggy software, and active threats against that software increasing so rapidly, that we will look back on this era as we do on the eras of exploding steam engines, collapsing medieval cathedrals, cities that were built out of flammable materials, or earthquake-unsafe buildings in fault zones. This doesn't mean that safer C++ isn't a good idea; but it's also clear that C++ is unlikely ever to become a safe language; it's too riddled with holes, and the codebase built on those holes too vast, for all the problems to be fixed.
- pjmlp 2y agoWhile it is great that this is happening, it seems a bit getting too late to the party. There is also the whole issue that standard working group, and the folks that actually work on C and C++ compilers, nowadays it is a very thin Venn diagram for the intersection of both groups. So it remains to be seen how much of this will actually land on compilers, and in what form. Nevertheless there are many C++ written tools that most likely will never be rewritten into something else, so any improvement is welcomed.
- dgellow 2y agoAccording to Herb’s article most of this is already available in compilers
- AlotOfReading 2y agoIn mainstream compilers. Most of these options aren't available in compilers e.g. for safety critical code.
- pjmlp 2y agoPartially.
- steveklabnik 2y agoDepending on how you look at it, that raises the question of "if this is so effective, and it's already available, why hasn't the situation improved?"
- pjmlp 2y agoAs many of us point out, even those that actually apreciate C++ despite its warts, safety culture or lack thereof. Which I think it was much better back when it was C++ vs C in the C++ARM days, with great compiler provided frameworks, eventually past C++98 there seems to have been an inversion, as C++ graduality took over domains where C ruled. The same mideset that will reach out for unsafe language constructs, regardless of the programming language, without any kind of profiler information, because of course it is faster and every μs counts.
- dist-epoch 2y agoThe C++ people were kind of ignoring the safety problems and Rust, but when Microsoft suddenly announced that all new code will try using Rust first, it's like suddenly they woke up and realized this is not a fad and that the gun is pointing at their heads.
- like_any_other 2y agoAs amusing as it is to imagine language developers getting executed when their language falls out of favor, I think most C++ people are happy about Rust. The problem are large codebases already in C++ that won't get rewritten, so we have to do the best we can, within the constraints of C++.
- IshKebab 2y agoDepends what you mean by "C++ people". I think most of those C++ people who are happy about Rust would say they are now Rust people who may be forced to use C++ sometimes.
- bluGill 2y agoNo, I'm still a C++ person because while Rust is intriguing I have so much existing C++ it would be billions of dollars to rewrite to rust and it will take years to get more than a trivial amount of Rust. For the vast majority of new features the cost to implementing it in Rust is far higher than the cost of doing it in C++.
- otabdeveloper4 2y agoPretty much everything Microsoft does is guaranteed to be a fad. They announce a new language paradigm shift every 10 years. (And then abandon it 10 years later.)
- gpderetta 2y agoMS is a large contributor to the C++ standardization effort.
- mafuy 2y agoI think I'm misunderstanding something. The post sounds like UB has already been mostly eliminated from recent versions of C++. But to my knowledge even something simple as `INT_MAX + 1` is still UB. Is that false?
- saagarjha 2y agoNo, it’s true. None of these efforts significantly change the prevalence of UB in C++.
- nmeofthestate 2y agoI think you are misunderstanding the post - it specifically says that there's "a metric ton of work" to be done to address UB, not that it's mostly a solved problem.
- bluGill 2y agoStop using `INT_MAX + 1` as an example! It is the worst possible example you can give (though easy to understand). Such code is essentially never a memory safety issue and not to what most people worry about UB. In the vast majority of cases it doesn't matter what `INT_MAX + 1` does you code it wrong. Sure there are a few encryption cases where it is fine, but the vast majority of cases your code as a bug no matter what the result it. If the variable netWorth is at INT_MAX there is no value of adding 1 that is correct. If the variable employeeId is at INT_MAX all values of adding 1 are going to collide with an existing employee. Meanwhile if you define INT_MAX+1 you force the compiler to add checks for overflow INT_MAX in addition operations even though most of the time you won't overflow and thus have needlessly slowed down the code. UB causes real problems in the real world, but INT_MAX+1 is not one of those places where it causes problems.
- AlotOfReading 2y agoINT_MAX+1 is actually a great example of UB because it demonstrates how UB is a problem even if there's a completely reasonable runtime behavior. One of the big reasons UB is problematic is that it invalidates the semantic guarantees the standard makes about all your other code. That signed integer overflow completely invalidates any sort of formal proofs or error handling you might otherwise have.
- saagarjha 2y agoThe problem here is that these don’t actually solve the problems that attackers use to exploit software written in C++. Nobody cares what constexpr code can’t UB (I thought it already couldn’t…?). Attackers will take your object and double free it and there’s nothing in here that will stop them from doing that. Fixing this in C++ is actually very difficult and unfortunately the committee doesn’t want to do this because it would change the language too much. So we’re only getting the minor improvements, which are nice, but nowhere near what is necessary to “tame UB”.
- gw2 2y agoA question to security experts reading this thread: What is your opinion on deploying C++ codebases with mitigations like CFI and bounds checking? Let's say I have a large C++ codebase which I am unwilling to rewrite in Rust. But I: * Enable STL bounds checking using appropriate flags (like `-DGLIBCXX_ASSERTIONS`). * Enable mitigations like CFI and shadow stacks. How much less safe is "C++ w/ mitigations" than Rust? How much of the "70% CVE" statistic is relevant to such a C++ codebase? (I've asked this in an earlier thread and also in other forums, but I never really got a response that does not boil down to "only Rust is safe, suck it up!". It also doesn't help that every other thread about C++ is about its memory unsafety...)
- rwmj 2y agoSTL bounds checking isn't bounds checking. Your code (or other libraries you use) can still have simple pointer arithmetic that goes outside bounds. But the larger problem is that bounds checking (even ASAN) isn't as good as statically checking code. ie. Your code with bounds checking still crashes at run time, which can be a denial of service attack, whereas with static checking your code would never have compiled in the first place. Nevertheless if you don't want to rewrite the world, then using these mitigations is much better than not using them. I would also add fuzzing to the mix.
- gpderetta 2y agoDoS is vastly better than an RCE. And safe code can still panic. But as you mention, unfortunately enabling bound checking in the STL wouldn't catch a lot of pointer manipulation. It would still be better than the the status-quo.
- UncleMeat 2y agoFor the first one, a lot of this depends on how modern your codebase is. STL bounds checks work great (and have remarkably low overhead) if the vast majority of your code is working with standard library types. Maybe all of the code that might have been a c-style array in the past is now using std::vector, std::span, or std::array and so you've got built in lengths. Not perfect, of course, since you can still have all sorts of spatial safety issues with custom iterator implementations or whatever, but great. But my hunch is that the vast majority of C++ codebases aren't using std::span or std::array everywhere because there is just a lot of much older code. And there's no comparable option for handling lifetime bugs. Tools like CFI or hardware memory tagging or pointer authentication help, but skilled exploit creators have been defeating techniques like these for a while so they don't have the "at least I know this entire class of issue is prevented" confidence as bounds checks inserted into library types. The general industry recommendation is "if you are starting something new that has security implications, please seriously explore Rust" and "if you have a legacy C++ codebase that is too expensive to port please seriously explore these mitigation techniques and understand their limitations."
- uecker 2y agoIn C, we made clear in C23 that there is no true time-travel UB and have eliminated about 30% of UB in the core language for C2Y as part of an ongoing effort that will eliminate most of the simple cases of UB. We also have plans to add opt-in memory safety mode proving full spatial and temporal memory safety. Having said this, I think the sudden and almost exclusive focus on memory safety is weird. As a long-term Linux user, this is not my main problem. This is what people building app stores and non-free content distribution systems need and they now re-engineer the world according to their needs. There are lot of things compromising my online safety and freedom, and certainly memory safety issues are not very high on this list. Finally, what Rust achieves, and what a memory-safe mode in C will hopefully also achieve in the future, is also just an incremental improvement. As long as there in unsafe code, and in practice there will be a lot of unsafe code, there is no perfect memory safety.
- Sharlin 2y agoI’m not sure how you can even try to juxtapose technical issues like memory safety with sociopolitical problems like corpo interests being in conflict with the interests of the common people. The formeer can be alleviated with technical solutions. There’s nothing that a programming language can do about the latter. Also, I question your claim that memory unsafety is not of great importance to regular computer users. Perhaps not if your computer is airgapped from the internet and never gets any unvetted software installed. Otherwise, have you missed the primary cause of the majority of CVEs issued in the past decades? Do you not think that the main technical problem behind countless security vulnerabilities, that have very concretely affected tens and hundreds of millions of people, does not deserve the attention that it’s finally starting to get? Google has reported that the mere act of stopping writing new code in memory-unsafe languages has made the fraction of mem safety vulnerabilities drop from >80% to ~20% in a few years. This is because bugs have a half-life, and once you stop introducing new bugs, the total count starts going down asymptotically as existing bugs get fixed. Finally, since you inevitably mentioned Rust, memory safety is indeed a necessary but not sufficient condition in software reliability. Luckily, Rust also happens to greatly decrease the odds of logic bugs getting in, thanks to its modern (i.e. features first introduced in ML in the 70s) type system that actually tries to help you get things right. C is never going to have those parts, the “if it compiles, it is correct by construction” assurance. C++ has janky, half-assed, non-orthogonal, poorly-composing, inconsistently designed versions of a lot of the stuff, but it also has all of the cruft, and that cruft is still what is taught to people before the less-bad parts. And because C++ is larger than the most people’s brain capacity, most people can’t even get to the more less-bad parts, never mind keeping up with new standard versions.
- agwa 2y ago> It’s working: The price of zero-day exploits has already increased. The only thing they've shipped is no UB in constexpr code - i.e. code that wouldn't have been reachable by attackers in the first place. How could that possibly be the reason for the price of zero-day exploits increasing?
- qalmakka 2y agoThis is nice and all, but the main issue with UB and C++ IMHO has never been that "nice", modern codebases are problematic - modern C++ in the hands of competent people is very nice, really. The problem is that 90% of all C++ development ATM is done either on legacy codebases full of ancient crap or with old frameworks and libraries that spam non-standard containers, raw pointers, allocate manually, ... In my experience, introducing modern C++ in a legacy codebase is not that much easier compared to adding Rust to it. It's probably safe to argue that C++03 stands to C++26 almost like K&R C stood to the original C++
- virtualritz 2y agoThere is no end to what a(n old) white man thinks he can do. ;) As an old white man who switched from C++, for a over a quarter century, to Rust, about seven years ago, the fallacy at the root of Herb's piece is all too well understood by me.