On top of that, memory safety vulnerabilities are disproportionately high severity: "Memory safety vulnerabilities disproportionately represent our most severe vulnerabilities. In 2022, despite only representing 36% of vulnerabilities in the security bulletin (NOTE: down to 36% from 65% because of moving from C++ to Rust and other memory safe languages), memory-safety vulnerabilities accounted for 86% of our critical severity security vulnerabilities, our highest rating, and 89% of our remotely exploitable vulnerabilities. Over the past few years, memory safety vulnerabilities have accounted for 78% of confirmed exploited “in-the-wild” vulnerabilities on Android devices."
Imagine if in any other field, a process or technology were developed that cuts the number of high-severity issues in half.
For example, a modification to the standard anesthesia protocols that demonstrably reduces anesthesia-related fatalities by 50% in clinical practice.
And now imagine, in reaction to this revolutionary development, thousands of anesthesiologists publicly said things like "what matters is not the technique but the skill of the physician", "good anesthesiologists don't make mistakes like that in the first place", "but this new technique takes 1%-3% longer than the previous one" or similar.
Utterly unthinkable, isn't it?
Yet in software engineering, this is exactly what has been happening every day for more than a decade.
Software is not terribly different from that. The cost of replacing foundational software is tremendous, much higher than just "adopting a new protocol".
This is the exact equivalent of physicians continuing to use unsafe medical procedures, and what's worse, many of those engineers defend their dangerous practices by claiming there is no real danger in the first place if the programmer is "smart enough".
I'm currently not ready to dive into a whole new ecosystem, re-learn all the best practices, and unlearn what's worked very well for me with sometimes no good replacement. Best practice for Rust seems to be to avoid linked lists for example. I don't know what's the safe replacement for memset and memcpy to anonymous data structures (void pointers -- generic code) but I have a sense that it is more painful. The general recommendations seem to be to switch to different, more complicated datastructures with more failure modes, or to put boxes and Arcs around things.
I don't think this fits me - I like the feeling of understanding what I'm doing, and once in a while coming up with something that compiles and runs fast and robustly. If you can do that in Rust, good for you.
Another part is that it still seems easier to interface with existing ecosystems in C. I tried writing some Win32 Rust code once in an evening and I have to admit I failed. Maybe I picked the wrong bindings library or whatever. At this point in my life, I have little patience to spend my time like this.
I appreciate the work that is being done, and I feel it's not unlikely that at some point we all will switch. At this point though I feel I'm way more productive staying in my current habitat. And that's not only on me, but also that the ecosystem and developed practices likely are not quite ready.
Comparing the investment to simply washing hands and putting on gloves or following a checklist as a surgeon feels unfair to me.
The equivalent of a generic memcpy is probably something like a .clone() call on a generic type that implements Clone.
Probably not the Clone trait but the Copy trait.
If you type "memcpy" into the documentation search, rustdoc will point you to
* https://doc.rust-lang.org/stable/std/primitive.slice.html#me...
* https://doc.rust-lang.org/stable/std/intrinsics/fn.copy_nono... (Though it should really point to the reexport at https://doc.rust-lang.org/stable/std/ptr/fn.copy_nonoverlapp... )
The latter will also mention
Implementing linked list in any language that is not memory-safe is challenging because of safety issues. Rust just points it out.
I don't feel that I am less in control, just that all of that needs to be put in code and not just go "okay, I know this part don't need a lock coz I will never call it concurrently" and hope for best.
Even writing for embedded (as in no os, tens of kilobytes of RAM microcontrollers) haven't been too bad althought I haven't managed to convince borrow checker to borrow non-contigous block of bits from a register yet... althought that's what unsafe{} is for after all
> Comparing the investment to simply washing hands and putting on gloves or following a checklist as a surgeon feels unfair to me.
The closer one would be "read that 300 pages of how to do stuff safely and apply it". Once you get into good habits it's not a problem but investment is there
> New projects written in C are being started every day.
But it is mostly about existing software, even if its not about replacing existing software. I write C++ code every day. I hate it, and I'd rather not. But I use C++ libraries written by my teammates, and reference implementations in prior C++ work in our past projects, and have a set-up C++ toolchain, and my company even has all sorts of written C++ docs and style guides and linters and macros and ... and ...
Even if we wanted to stop, there's so much extra stuff to consider. I get your point, <<why start a new thing knowing there's a better way?>> and I would want to stop using c++ but most software isn't one-and-done like a surgery. It is a continuous commitment and ongoing operation, it is the tools used, and the knowledge learned, and the libraries built.
> This is the exact equivalent of physicians continuing to use unsafe medical procedures
Plenty of platforms don't support rust. Just because you've improved knee surgery, doesn't mean it works on an elbow... yet. And sometimes you still gotta perform surgery on elbows.
> if the programmer is "smart enough".
Can't defend this, but tbh I've never heard it.
> Can't defend this, but tbh I've never heard it.
Take a look at this comment: https://news.ycombinator.com/item?id=33824934
> Modern C++ has many memory safety features. If a company has learned that its people fail to use them, then bad for them.
It is a somewhat common attitude in this type of thread.
Except the safety features are often a lot easier to use than the original C isms that tend to cause the most issues. So it is less an issue of smart and more one of bad habits. C strings instead of std::string, plain arrays instead of std::vector, implicit ownership instead of smart pointers, ... .
The first Google Style Guide for C++ I ever came across in the wild espoused C with classes, had "standard" in scare quotes and banned most of boost for encouraging functional programming. I almost threw a fit when someone unironically tried to push that POS at work because "Google", it was entirely nonsensical especially given that we made heavy use of boost and math libraries with operator overloading.
Especially since Google has a ton of automated tools to perform tests and analysis on code, and enforces certain behavior before you can merge your code in. Something that is probably missing from a smaller organization that’s simply adopting their style guide. Also probably missing is googles alternative stdlib they use.
This is not about C++ developers using old school C approaches. The language is fundamentally dangerous. There were huge efforts within Chrome to get all memory managed by smart pointers even more powerful than those offered by the standard, and they still have UAFs all the time.
It’s hacker news. People say all sorts of inflammatory crap here. I discount anything said here, especially in response to an article about said topic.
If my c++ writing coworker shared that opinion with me, or someone at a conference, that’s be different.
> Modern C++ has many memory safety features. If a company has learned that its people fail to use them, then bad for them
I will admit I vaguely agree with this. My company has all sorts of tools that perform basic checks for memory safety and a style guide that is very opinionated. Just because we can’t switch easily doesn’t mean we can’t try to improve as an org.
I don’t avow the belief that any program is truly smart enough/too dumb to make bugs, but I do think the organization maintaining the code has a responsibility to improve. Especially a large organization. Whether that’s better code review processes, automated tooling, or even soft-banning the use of certain unsafe practices.
> Plenty of platforms don't support rust. Just because you've improved knee surgery, doesn't mean it works on an elbow... yet. And sometimes you still gotta perform surgery on elbows.
That's a non-argument, obviously if it isn't even applicable it's not a discussion. Also most of what people code on does support Rust
>> if the programmer is "smart enough".
>Can't defend this, but tbh I've never heard it.
Programmer is never smart enough. Decades of bugs showed that
And why do you think it's wrong, per se?
> This is the exact equivalent of physicians continuing to use unsafe medical procedures
You mean with different safety tradeoffs?
Because what you propose is exactly like forcing very expert physicians to switch to a procedure they are novice of and that it's not been battle tested like the old one, that proved to be very effective in most cases.
It's the same reason why patients prefer to be treated with established procedures and to undergo experimental treatments they need to sign a document that proves their informed consent.
The issue is not "bridge is suboptimally designed" or "bridge will need some extra maintenance because something started to break".
The memory safety issues are "some cars randomly explode when passing that bridge" or "when driver breaks 6 seconds after entering the bridge, every other driver dies.
> Software is not terribly different from that.
It is MASSIVELY different, especially anywhere near anything security-related. Most buildings don't have a group of people with hammers trying to find a weak point that will never happen in any actual use conditions and then hit that weakpoint in every similar building built in every place of the world.
Please don't make horribly useless comparisons like that
All the time! And the stuff we don't tear down, we retrofit.
The attitude "it's just computers, nothing truly important like medicine" might have been viable 40 years ago, but it certainly isn't anymore.
The earth is still spinning, despite so many things not working everywhere. That's not just in software. In every system, there's relatively few single points of failure. As you zoom out, failure points disappear and new ones appear.
Sure, still sometimes someone notices a critical security flaw that's been in there for a while, and that had found its way into large parts of the infrastructure already. (The last one I heard of was not a memory vulnerability).
https://qz.com/646467/how-one-programmer-broke-the-internet-...
If this breakage is an argument for anything, it is against depending on lots of code that you don't even know. The last Rust projects I tried to build all had on the order of 500 transitive dependencies, by the way.
No. Ignaz Semmelweis faced it in the 1800s for daring to suggest (what we know know as germs) made people sick and hand washing could drastically reduce medical complications. He was able to prove it too.
By the end was locked up in an asylum for his ‘crimes’.
Want more recent?
How many stories have you heard of instruments or gauze or whatever left in surgical patients? Of operating on the wrong part or person?
People are fallible. But checklists help a ton. We know that for sure. Why is aviation obsessed with following them? Because they work to increase safety.
Surgeons have resisted them. I don’t know the current state of it, but they were making that exact “good surgeons don’t need it” argument. I remember it being a plot point on an episode of a medical drama (ER? Or maybe Grey’s Anatomy).
There are probably tons of other examples in other fields.
Surgeons resisting checklists is new to me. Do you have a reference other than a TV show? My understanding until now was that checklists are extensively used in medicine.
> Despite all the evidence, Gawande admits that even he was skeptical that using a checklist in everyday practice would help to save the lives of his patients.
> "I didn't expect it," Gawande says with a chuckle. "It's massively improved the kind of results that I'm getting. When we implemented this checklist in eight other hospitals, I started using it because I didn't want to be a hypocrite. But hey, I'm at Harvard, did I need a checklist? No."
https://www.npr.org/2010/01/05/122226184/atul-gawandes-check...
Not sure if this supports the reluctance idea since it says 93% use checklists, but most surgeons don't think it improves safety.
> Of the 353 survey respondents, 93.6% use SSCs and 62.6% would want one used in their own child’s operation, but only 54.7% felt that checklists improve patient safety.
The part you quoted from your second link directly contradicts your claim that most surgeons don't think it improves safety (even if the 54.7% is among the 93.6% that use it that still gives 51% that think it improves safety).
> Yet in software engineering, this is exactly what has been happening every day for more than a decade.
Consider what happened to poor Semmelweis when he discovered in the middle of the 19th century that hand-washing improved medical outcomes: doctors of the time were too proud to accept his results and drove him out of the profession (and to his early grave) rather than change their practices.
All these people who insist on continuing to write new C programs have the same mentality as those doctors who refused to wash their hands.
A bit much, eh? I write programs in whatever I want as an hobby. Why does that make me a murderer? Everyone needs to chill about this.
Not really. Rust is the first major attempt to achieve c/c++ performance & capability while also being safe.
Prior to that nearly every memory safe language came with crippling tradeoffs, and that is why people rejected them. Especially as performance and efficiency took center stage again with the massive increase in battery powered devices & the general plateau of single core CPU performance over the last decade
This says more about those C++ defenders.
Nitpick, this is not quite true. Memory safe languages are what you should be using in contexts where security and reliability are critical. This is generally the case but there are some contexts where other concerns are genuinely more important. Of course when this is necessary is often misrepresented but these cases do exist.
Raw memory access is something you normally need to create vulnerabilities, not to exploit them :)
It's an ergonomics thing, not a "can't" issue. There is a reason I called out Swift in particular—their "unsafe" APIs are so horrid to use that they make you regret doing unsafe things in the first place. Plus, throw in FFI and now you've got an even worse problem because not only are you forced to use the unsafe types, but often a lot of the critical APIs you need to interface with (in *OS exploitation, mach is the worst offender) have such funky types due to their generic nature that you have to go through half a dozen different conversions to get access to the underlying data.
https://github.com/hellman/libformatstr
You can do something like this, no need to work with raw memory.
Not everybody is writing security-critical code. For some things productivity and time-to-market is more important and security is not enough of a concern to justify dealing with a language with horrible compile times and a self-righteous, dogmatic community.
After memory safe languages become a bit more battle tested, C/++ needs to be regulated like asbestos.
There are some things that the language is good at, but at some other things (I think a lot actually) it isn't. At the very least, I wouldn't recommend it for writing a video decoder.
In nearly 10 years of professional Haskell I've never come across a practical situation where extensions that were mutually incompatible. Can you name any extensions that are incompatible in a way that actually matters in practice?
Some of these things would make working in the language pretty painful. I remember trying some library to toy around with a basic 400 line OpenGL program. It always needed 8 seconds to rebuild at the time. I don't recall and probably didn't understand why, but I suppose it has to do with some extra type or template hackery in the library that would just overcomplicate everything, probably even at the outset.
What remains is the feeling of, I can't do this thing yet in the type system, so take that extension. Oh wow. Now I can't do this other thing that I also need, the only fix is another extension (if it's available yet). I couldn't get around of this feeling of constantly having to hack around the language.
In my experience you need to have a very good overview and understanding of all the available tricks and extensions to be able to navigate your way around the language and not paint yourself into a corner. Maybe I have the wrong personality, the wrong motivations, or am just not smart enough. Obviously I'm not you, and am not Edward Kmett (who would resort to lots of GHC specific hacks and drop down to C++ as well).
This is a fair criticism. Compile times are slow.
Extension confusion is not a fair criticism. Extensions typically remove restrictions. They don't create incompatible languages.
Granted, it's a bit annoying to have to turn them all on, one by one. These days one should just enable GHC2021 and forget about language extensions. That saves one having to be Edward Kmett, or from bothering to think about language extensions at all.
If you write in C and your program is complex enough, you will spend a lot of time just chasing segfaults and concurrency bugs and getting it to work the first time you write it. If your systems programming is in userspace, that's sort of fine. But if you're in kernel or on bare metal, the cost of debugging goes up by an order of magnitude. There's no debuggers on bare metal, and nobody can tell you how your program crashed—the device just stops responding, that's it.
That's why safe languages make even more sense in these restricted environments. If you get twice fewer memory safety bugs while you're getting your program to work, that can reduce your development time like 5-6 times.
So now you need to make your interrupts talk to your Java objects? Is this any safer?
Is it easier to get a VM running in your kernel (probably no mean feat to do that in the first place) and you'll never get any concurrency bugs? And if you reduce memory bugs by half, those will be easier to debug?
And you won't be annoyed that you can't guarantee to be able to link objects in queues (because of allocation failure) and access them with generic code to copy data, link/unlink them, and so on? You're fine to pay for callbacks and interfaces everywhere, both in terms of runtime and performance as as maintenance headaches?
I'm asking incredulously, but seriously. Because frankly I've never looked at a project like MirageOS or whatever. But given real world evidence of what has survived, I don't see why you should assume I'm joking.
That you can't debug a "bare metal" kernel isn't quite true, either. But sure, the more complex a system becomes, the more contemplation it requires to figure out problems. This is universally true, but you can't simply discuss complexity away. And adding complex object models on top without consideration doesn't make your task easier just like that.
Are we really talking about the “price” of managed code, when C code is chock-full of linked list data structures? A list of boxed objects is more cache-friendly than that. It is simply not always that performance sensitive to begin with (e.g. does it really matter if it queries the available display connectors in 0.0001s or 10x that?)
Regarding MirageOS, they actually achieved better performance by using a managed language than contemporary C OSs for select tasks. This is possible due to context switches being very expensive, and a managed env can get away with (some?) of those.
Context switching can be expensive, but I don't see what's specific about managed envs about that. Fundamentally you have to have trust in code, and need to have the hardware support to enforce authenticity of the trusted code in order to avoid context switching. Maybe a promising development is CPUs growing more and more cores, and more and more kernel resources being available through io_uring and similar interfaces.
How did we start talking about Java and VMs? Is this some sort of strawman argument?
> But sure, the more complex a system becomes, the more contemplation it requires to figure out problems
Strawman again? I wasn't talking about complexity. I said that the more "systems" your programming is, the higher is the cost of memory safety bugs.
Is it a strawman if my comment was in response to "managed languages"?
> Strawman again? I wasn't talking about complexity. I said that the more "systems" your programming is, the higher is the cost of memory safety bugs.
For clarity, you spoke about the cost of debugging of memory bugs. And I said, it's universally true that programs are harder to debug the more "systems" it gets. That's because it typically isn't sufficient to simply trace an individual thread anymore. "Logical tasks" are served over a number of event handlers executed in various (OS) threads.
It's not first and foremost a refutal of what you said. But an observation that I even placed in opposition to my other statement that it's not quite true that you can't use debuggers with kernels. FWIW and so on. I don't get why you are calling "strawman" repeatedly, and don't get the aggressive tone of your comments.
Who would choose C/C++ and not something like Go in that situation?
I think whether there "should" be a law making you liable could depend on the details of the exploit.
If you get exploited via rowhammer, I don't think anyone would blame you. It would be unreasonable if every small business running a website could be sued if they didn't defend against electromagnetic interference within the RAM.
However, if you're Apple and say -- you could get pwned because someone clicked a button to register version 9000 on the public npm/pypi registry (https://medium.com/@alex.birsan/dependency-confusion-4a5d60f...) -- maybe I agree there's an argument for some accountability there :)
Computing is the only industry, where people accept to live with tainted goods instead of forcing whoever sold them to pay back, cover for their damage or whatever.
We already have high integrity computing, digital stores with returns, consulting with warranty clauses, and some countries are finally waking up that computing shouldn't be a special snowflake.
https://www.twobirds.com/en/insights/2021/germany/the-german...
I agree if there's a high social cost to a breach then the government should punish those involved. Also, the security of your software depends on your threat model and which threats are in scope and you're willing to invest in protecting against. The tradeoff is ease of development and velocity. So maybe such laws will incentive this process differently, and maybe it's a worthwhile change.
I look at computing as a big experiment. Personally, I am very careful to use trustworthy services and don't depend on software for anything critical (besides banking, but luckily FDIC). Most people don't take the same precautions and rely very heavily. It's obviously critical infrastructure at this point. Maybe it's time to stop thinking of it as an experiment, and maybe these laws make sense.
I don't like the concept for emotional reasons; to me it's sad and signals another step towards the end of the golden age of the internet.
Worst Rust feature by far.
I understand how Rust solves some problems and these are indeed very important ones. But it still is a constraint that has to prove itself.
C is horrible, out of the question. Really dated too without thousands of band aids. C++ has millions of those. But why not start re-implementing stuff in Rust if that is so close to your heart?
We can also reimplement everything in JavaScript. It is memory safe too. Wait, where is the enthusiasm now?
Look at js package stats - that's exactly what's happening. Many of apps and packages created today in js would be created in C/C++ few years ago. People who learn programming today don't know what C/C++ is. If they need something low-level, it's Rust.
No matter what people do, it's never enough for the critics. Many people criticize Rust fans for "rewriting it in Rust"!
> how about just doing it
People absolutely are. That's what the article is about, even.
Defenders of C might note that Android is java and IOS is not and compare the security of those two systems and say clearly memory-safe is focusing on the wrong thing. This is equally true but no more valid an argument.
The one that really bothers me in all these language-booster discussions (that we should and need to have) is the functional programming formal verification claims. We have no ssl library written in a memory-safe, functional language that has been proven correct that has dominated the space. Heartbleed wasn't yesterday.
I look down the list here: https://en.wikipedia.org/wiki/Comparison_of_TLS_implementati...
And I think something is not being discussed as far as replacing memory unsafe languages of critical security infrastructure. What is it?
Heartbleed didn't affect https://hackage.haskell.org/package/tls even though it isn't formally verified.
Why hasn't this really good result meant _everybody_ now uses that library by default and has to justify using something else?
There is something here not being discussed, what is it?
There is something here, at least one thing, that seems to be dominating outcomes, and is not being discussed.
Nobody has even a half-suggestion of what it might be and that is not making it (or them) go away as problems that are not being solved.
And I don't know about "used at scale" but we use it in production for Pernosco.
You will find at the bottom of that page C implementations of curve25519 that are proofed and derived from F* and Coq. Curve25519 is a relatively simple implementation and only one part of any system that uses it. As you can see in both of these implementations the papers recognize a team of contributors each - this should provide some insight as to the cost of such work. That doesn't make it unimportant, it just makes it rare.
Wireguard seems to be written almost entirely in C, is that right?
1) The most cost-effective way to eliminate the majority of memory bugs is to just start writing all new code in a memory-safe language. If you were going to write new code anyway, you may as well do it safely.
2) Going back and re-writing existing code that doesn't need to be changed may solve latent memory bugs, but it will likely introduce other regressions that could be worse for security or for user experience. If code doesn't need to change, it's often better to leave it as is.
Not that a rewrite is never called for, but it's not necessarily the best course of action by any metric (even when neglecting the cost).
People tend to forget that they don't have to live with those problems, but they still have a cost
Defenders of C++ argue that there's no reason to change the language, because new features around safety guarantees are being introduced into every C++ standard starting from C++11 at a remarkable pace, so remarkable that compilers implement them faster than the existing adoption rate. And the adoption rate speaks volumes about existing capacity to port/rewrite big codebases in entirely new stacks. The new stacks also tend to have fewer custom static code quality analyzers from third-party vendors, and they are used a lot in mission-critical C++ codebases.
Are these static code quality analyzers detecting code quality problems that Rust and company are also vulnerable to? Or are they mostly looking out for the hundreds of legacy footguns that C++ still officially supports?
If they’re saying that C++ can’t be saved, maybe they’re worth listening to.
It might be true, but it also sounds like an appeal to authority. I suspect there also might be voices that are being silenced or aren't given a similar platform to speak up and provide an alternative viewpoint on the matter within the same organisation, because <team budget/political reasons why>. After all, there are greenfield projects that are being started in C++20 and people are enthusiastic about their prospects. I wouldn't just blindly dismiss their reasons in favour of Google ones.
That said, they won't catch a ton of memory and thread safety issues. You'll need tests with 100% coverage for that. Or you could just write it in rust and the compiler will catch it.
And full agree, all what cppcheck does imo should have long gone into the warning suite, and Werror and Wall should be the default..
If the authority comes along with a bunch of well researched and documented data from experiences in the real world… that seems worth listening to.
It’s no longer an appeal to authority. It’s just looking at evidence.
You’re merely reading what you want between the lines.
We continue to invest in tools to improve the safety of our C/C++. Over the past few releases we’ve introduced the Scudo hardened allocator, HWASAN, GWP-ASAN, and KFENCE on production Android devices. We’ve also increased our fuzzing coverage on our existing code base. Vulnerabilities found using these tools contributed both to prevention of vulnerabilities in new code as well as vulnerabilities found in old code that are included in the above evaluation. These are important tools, and critically important for our C/C++ code. However, these alone do not account for the large shift in vulnerabilities that we’re seeing, and other projects that have deployed these technologies have not seen a major shift in their vulnerability composition. We believe Android’s ongoing shift from memory-unsafe to memory-safe languages is a major factor.Modern C++ has many memory safety features. If a company has learned that its people fail to use them, then bad for them.
Of course, there are languages that abstract memory safety to the point that they eliminate those types of mistakes. But languages are tools for a job, and only some tools are applicable where C++ is applicable. We should not bury C++ prematurely before answering the question - "what else is as fast and efficient as to replace it for OOP?" And if a project doesn't need fast and efficient code, then why is it using C or C++ in the first place?
Overall, selecting the correct tool for a job is more important than figuring out which tool is better in some abstract way.
And a good workman put his old/obsolete/dangerous/etc tool behind when something better show up.
The bad workman, instead, continue blaming his tools, when the problem is that he CONTINUE using bad tools, anyway!.
P.D: I learn about mechanical engineering. Get rid of bad tools fast is like key around that...
This recapitulates an argument at least as old as C89. You can probably find Usenet posts deploying it to argue against the adoption of strncpy, because if people don't know how to use sizeof and strlen, then bad for them.
C++ nowadays can be used in a very memory-safe way without much effort. In my professional experience, memory leaks and corruptions are sporadic in modern C++ code and common in old-style pre-C++ 11 code.
That's why I'm a bit skeptical of this article from Google. It seems reasonable that Android has quite a lot of pre-C++ 11 code. And the article seems to lump two very different approaches to memory safety in pre and post-C++ 11 style programming.
Another approximation is to look at the Android source tree to see what proportion of it is as old as you assume in your argument. There are 431 results for a search `"Copyright 200" filepath:.\.cpp`. There are 7465 results for `"Copyright 201" filepath:.\.cpp`. 4152 results for `"Copyright 202" filepath:.\.cpp`. 220 for 2012, 354 for 2011. If you exclude tests the ratio is even less favorable for your theory.
In case you're wondering the project policy is to add a copyright header at the time the file is created, they do not update years in headers arbitrarily. As a spot check the first file matching "Copyright 200" that wasn't just essentially C code wrapped in extern "C" was: external/angle/src/libANGLE/Config.cpp. This file contains the use of std::make_pair.
You can perform these searches yourself here: https://cs.android.com/search?q=%22Copyright%20200%22%20file...
I've looked at many "Copyright 201" and "Copyright 202" headers. I needed to see more use of C++ 11 or equivalent smart pointers or containers to say that this codebase uses modern C++ memory safety features. Other modern C++ features (like std::make_pair that you mention) are easier to spot.
I expect this codebase to have many memory safety issues. It may not pass code review in a company/team that expects their people to use modern C++ memory safety features. After seeing it, I'm more convinced that the reason Google has so many problems with C++ in Android really is because they don't insist their engineers use modern C++ (or equivalent in-house containers/pointers).
Here's another insightful pair of searches:
" std::make_" filepath:.*\.cpp
"delete " filepath:.*\.cpp
The style guide, C++ readability, and general code review has all but banned raw "new" for years and years. You can find plenty of CVEs where the root cause is a UAF on a managed object.
Thanks for the context about UAF. I am curious about this. Much of my C++ experience comes from working with in-house reimplementations of std/stl, so my question might be a bit stupid, but how is use after freed of an obj managed by smart pointers so prevalent? Should the smart pointer not be nulled after the object is destroyed? Maybe you have a good example CVE? Are these cases of using the raw pointer in the smart pointer without checking it first?
I'm not sure what you are going for here.
The way this often happens is there is some module that owns an object with a unique_ptr and references to that object are used elsewhere. But the ownership of the object is complicated so a bug sneaks in where a non-owning reference to the object gets dereferenced after the unique_ptr is deleted. You can prevent this by having literally everything use shared_ptr for everything but that sucks for lots of reasons.
You can avoid multi-ownership problems of shared ptrs with weak pointer member variables (which only need to be turned into shared in a given {} scope). Some other problems can be solved by marking objects as pending kill without destroying them immediately and ensuring all threads finish access before actual deletion.
Unreal Engine uses both weak pointers and object marking in a global object array. It also uses GC but that's besides the point.
Would the same approach to modern memory management not help Android?
We've got like 30 years of people insisting that it really is possible to write safe C and C++ programs if you just follow the One True Way (TM) and its never been the case. Each new One True Way helps, but it sure as hell doesn't solve the problem altogether.
(And sure, it doesn't apply to every niche yet, but it sure applies to a lot of them)
Are you serious? A bad workman blames his tools, because workmen are reponsible for their tools. A large part of being a good workman is identifying what tools are good and using them.
And C++ is a terrible tool for any task where you are not forced to use it because of existing libraries. All the memory safety features of modern C++ are a tiny, almost vanishingly small step in the right direction.
> "what else is as fast and efficient as to replace it for OOP?" And if a project doesn't need fast and efficient code, then why is it using C or C++ in the first place?
If you need fast and efficient code, why on earth would you be doing OOP?
As I said in the comment to which you are responding, "selecting the correct tool for a job is more important than figuring out which tool is better in some abstract way."
> C++ is a terrible tool for any task where you are not forced to use it
Many game developers, OS developers, and massive hardware-software makers doing embedded programming who use C++ would disagree. What would you say to them?
> If you need fast and efficient code, why on earth would you be doing OOP?
For small projects, I could agree. What would your recommended alternative be for massive codebases in large tech companies that need fast and efficient code?
P.S. Please read https://news.ycombinator.com/newsguidelines.html about snarky comments. Thanks.
The poster wrote very clearly:
> where you are not forced to use it
If one is forced, there's obviously no option.
The idea is not that C/C++ should be replaced right now, rather, that devs finally understand that C/C++ should not be used where possible.
I actually see this pattern used by some, who defend C/++: "C/++" should be deprecated" - "No, it's impossible to eliminate C/++ today".
Deprecation is not elimination. Linux started introducing it, and Google is doing as well, so it can be done gradually.
>Are you serious? A bad workman blames his tools, because workmen are reponsible for their tools. A large part of being a good workman is identifying what tools are good and using them.
Also C/C++ made into real life tools would be OHSA violation on OHSA violation in real world
We have an answer: Rust. It's no longer premature, bury it.
See how many reference types are there, how async is handled and the underspecified unsafe semantic.
For higher level tasks, I prefer a language with GC like go or java. Rust can work with references counting, but it don’t mix well with the larger ecosystem. For lower level task, the underspecified unsafe model make it worse than C aliasing problem
2, & and &mut. What else?
I would love to know about any projects that do OOP well in Rust.
Concepts like sugar syntax and syntax salt do exist
Approaches to problems may vary by languages because lang environment shapes its users in some ways
Google's one of the worst C++ shops because their code standard basically forbids using modern C++, and their C++ is more like 90s Java than modern C++. It's no wonder they want to get away from it.
I write C++ at Google, and it encourages use of modern C++ features, and many things you see adopted in std have roots in our libraries.
I'm curious what you think Google prevents us from using and why you think our C++ is like 90s Java.
https://abseil.io/tips has a lot of our philosophies and abseil is chunks of our internal libraries published externally.
I think it stems from the fact that Google was slow at making C++11 available internally so there was a period of time where the rest of the world was using smart pointers and we couldn't. That may have just solidified a "Google uses old C++" meme out in the wild despite it being wildly out of date.
Modern C++ is indeed a huge upgrade on what came before and with a good amount of static and dynamic analysis the state of low-level programming is much better now, but there really is no reason for new programs to be written with these. Besides the bottom of the stack, managed languages are more than fast enough for nigh everything.
And yet, there is a lot of enthusiasm (at least here on HN) for web development in Rust...
Someone can think it's fine to write a web application in java/python/js and Rust.
It seems plausible that splashy projects in new languages are better for careers than grinding through "stable" codebases using "boring" engineering practices.
I also gather that Google has a challenge, possibly for similar reasons, keeping their third party dependencies updated and up to standards. A lot of those are written in C and C++, probably.
Designing the ultimate everything sanitizer with zero performance overhead would surely be impressive even at Google. Especially if it was actually adopted across the org.
And I assure you that, despite the memes, code health efforts do end up with promos here. The org responsible for third_party and large scale code health had above average promo rates for ages.
The same question comes up when an existing system is rewritten from language A to language B and big performance gains are seen. The language could be the big cause, but so could the extra engineering effort itself -- updated design, fresh attention to the requirements, etc.
Reducing defects is one of the main reasons (others being maintainability, readability, better integration, and similar) for refactoring and rewriting code. There's usually not enough time/money to do it, especially for large codebases.
I quite like rewriting parts of a codebase to modernize it, and I have often closed tons of bugs in a short time this way. It is definitely effective. But not as cost-effective as deprioritizing bugs into "won't fix" territory, which is what many companies like to do.
Yes, things have gotten better. Smart pointers are a godsend. Sanitizers are a godsend. Various static analysis tools work pretty well.
But even codebases that adopt all of these things religiously still are riddled with security vulns.
#RustForTheWin
Well, first of all, this is said but not proven.
But it's easy to prove that memory safety bugs are not a significant percentage of the total number of bugs, even Google agrees.
Vulnerabilities are not the same thing as bugs, a vulnerability like spectre or meltdown are not due to a bug in the software, have an ubiquitous immediate impact on 100% of the devices and are much harder to fix or mitigate, sometimes it's could even prove impossible.
The same bias can be explained using the exact same words used in the article
"Despite most of the existing code in Android being in C/C++, most of Android’s API surface is implemented in Java. This means that Java is disproportionately represented in the OS’s attack surface that is reachable by apps."
It can be read as: of course most of the vulnerabilities are due to memory safety bugs, it's much harder to gain root privileges exploiting a bug on the colors of a specific element of the UI, assuming it would be possible.
It can also be read as: most of the userland software is based on Java, which is memory safe by default, assuming there are no bugs in the implementation of the JVM, which is entirely not Java.
Given that, the problems become
- rewriting the entire ecosystem in memory safe languages requires rewriting everything from scratch, which is a task that even Google will have huge problems to complete (reminder: Google is the number one killer of its own projects) in reasonable time or without wasting more money that it's worth on it. Is an half complete not battle tested complete rewrite actually safer? Historical data says it usually isn't.
- are the user actually safer when memory is safe? I mean, memory safety bugs gave us jailbreaking for locked devices, memory safe languages gave us bugs like CVE-2021-44832
I wouldn't classify the issue as black/white, there's a lot of grey to be considered.
Using language-independent bug example in discussion about language-caused bug vectors isn't exactly honest.
Rust would stop Heartbleed for example, and that was one of huge vulnerabilities
using a low budget project with few developers maintaining one of the most used libraries in the whole World as an example of non memory safe languages perils is not exactly honest.
Heartbleed could have been easily fixed if the companies profiting from using OpenSSL donated a few more eyes to look at the code.
Similarly to what happened to Log4j bug, which had an enormous impact, similar to the heartbleed one and affected a fully memory safe language.
Why? That's the situation of enormous amount of code people use.
Anyway heartbleed was discovered after many years, let's wait the same many years and see what kind of bugs we'll find in code written today with different languages.
Full disclaimer: I do not write C code since long time ago and have no intention of going back, but dogmatic programmers that believe in "saviours" are a real mistery to me.
The same people forgetting to free a resource are the same people that will forget to sanitize some input, meaning all of us make mistakes and will keep making them, in any language and those mistakes will be abused by some malevolent actor.
Google problems are not everyone's problems.
Goggle's solutions to problems are not everyone's solutions to the same problems.
Assuming that what Google says is applicable everywhere is at best naive.
.. unless said language makes making those mistakes difficult or impossible. Sanitizing input for example has not been an issue for me for decades, as every framework I used handles that by default, I'd have to work extra hard to make a mistake there.
> Google problems are not everyone's problems.
In this case they are. Not only memory safety is an issue for many codebases that have at least some C somewhere, but also because Google products are used by milions.
> Goggle's solutions to problems are not everyone's solutions to the same problems. > Assuming that what Google says is applicable everywhere is at best naive
Any other time I'd agree with you, but I don't see anything Google-specific here.
You're missing the point [1]
(or I was unclear)
Yes, improvements in neuro surgery can save lives, but the bulk of preventable deaths it's in human mistakes [2] that are almost impossible to make impossible.
Just like the majority of the bugs are not prevented using rust, just a minority of them, which are also arguably the hardest to find and exploit, while a SQL injection can be exploid by a script kiddie with average IQ.
[1] https://portswigger.net/daily-swig/mastodon-users-vulnerable...
[2] The three risk factors most commonly leading to preventable death in the population of the United States are smoking, high blood pressure, and being overweight.
"For more than a decade, memory safety vulnerabilities have consistently represented more than 65% of vulnerabilities". That's not minority. We are getting into minority territory now because of Rust and other memory-safe languages.
> while a SQL injection can be exploid by a script kiddie with average IQ.
Use any framework and it's solved problem.
Defenders of C/C++ frequently note that memory safety bugs aren't a significant percentage of the total bug count, and argue that this means it's not worth the hassle of switching to a new language.
Google's data suggests that while this is true, almost all severe vulnerabilities are memory-safety related. Their switch to memory-safe languages has led to a dramatic decrease in critical-severity and remotely-exploitable vulnerabilities even as the total number of vulnerabilities has remained steady.