5 million Rust LOC
One potential memory safety vulnerability found
Rust is 0.2 vuln per 1 MLOC.
Compared to
C and C++ : 1,000 memory safety vulnerabilities per MLOC.
There are certain places on the internet where any mention of rewriting in Rust is met with scorn and ire. And while, like any technical decision, there are pros and cons, I cannot see why in the face of astounding evidence like this, you would completely dismiss it.
And I say this as someone who has never written a line of Rust in their life (some day I'll find the time).
In my experience, the loudest critics of Rust I have heard are actually seasoned C and C++ developers who are incredibly good at one or both languages, but know almost nothing outside it.
On one hand, C++ is an incredibly complicated language that one can invest considerable amounts of time into. It also used to occupy a unique niche where you get tons of abstraction features yet as much blazing speed as you care to spend time optimising. Rust is encroaching on that niche.
On the other hand, C is an incredibly simple language, which does not allow for convenient expressions of particular abstractions. If they hated C++ because it was too hard to follow. What the code is doing, they probably hate rust for the similar levels of abstraction affordances.
When I hear the bad faith arguments from people who really should know better, what I hear is a group of scared developers who have been able to coast on their knowledge base for years or even decades, and are now feeling like their skill set is at risk of being unnecessary.
It always seemed like an unproductive attitude to have in a knowledge-based industry like software development. I am also a C++ developer, but you bet I am learning Rust on the side, because I think it's a good idea to skate where the puck is headed. I also learned enough of Zig to be dangerous a few months ago because it was fun.
Either way, I would suggest those developers reflect on the reason why they have this reflexive need to throw a wrench into any conversation mentioning rust. If their intention is to slow down adoption through hostile community sentiment, it's not working.
An earlier Google blog post from the same series (link in the first sentence) pointed out why: new code tend to have more vulnerabilities than established code. So it makes more sense to write new code in Rust than to rewrite old code in Rust. After all new features are still being added and new code needs to be written; it’s not like the codebase is done with features.
> I cannot see why in the face of astounding evidence like this, you would completely dismiss it.
We're decades into the global warming era. You simply can't make some people accept evidence if the conclusions from that evidence would be uncomfortable to them.
If people don't take exploitability seriously, you can't make them. Well, unless you keep pwning them.
People are worried about half-assed[0] rewrites that break functionality and introduce exciting, new vulnerabilities due to improper implementation. And they aren't wrong to fear that, given the multiple issues we've seen in just the past week with Ubuntu's Rust overhaul.
[0]: Or even whole-assed. Memory (un)safety is only one form of vulnerability.
I think that it would be foolish for any software engineer to completely dismiss any technology. There is a time and place for any tool, and it is a job of a competent engineer to determine what the appropriate combination of these is that would solve a certain problem within specific constraints.
That said, memory safety is one criterion out of many that could be used to make that decision. For a large number of software projects, memory safety simply isn't a major concern. Ease of use, iteration speed, developer familiarity, availability of specific libraries, and so on, are often equal or greater concerns than memory safety.
So, sure, if you're writing a kernel, operating system, or a mission-critical piece of software, then Rust might be worth considering. Otherwise, you might be better served by other languages.
> I cannot see why in the face of astounding evidence like this, you would completely dismiss it.
Because it's not a silver bullet. That safety comes at a cost; Rust is much more difficult to learn than C or Zig and the compilation time for code with equivalent semantics is an order of magnitude greater. It has also added a great deal of toolchain complexity to projects like the Linux kernel.
People have decided that the pros outweigh the cons in those particular cases, but those cons exist nonetheless.
>"There are certain places on the internet where any mention of rewriting in Rust is met with scorn and ire."
Nah. For me it induces vomit. Any time the vulnerability is mentioned a horde will arrive promptly and sing "rewrite the ... " in Rust.
For fuck's sake. We got it. We know it is mostly memory safe with bunch of other protections baked in. So go and rewrite it and then try to sell it to your customer and have them pay for this job. If you succeed - congrats, good for you and for the "victims". If not - stop nagging people who have other things to worry about.
One who has tried the language and hates it can completely dismiss it. Memory issues can be fixed in ways that don't involve rewriting millions of lines of code and the ensuing chaos, feature degradation, retraining, etc. that goes with it.
It's one class of bugs. This is not enough information to make a technical decision. Logic bugs still exist. It's not clear if these are easier or harder to create in Rust. There is some existing evidence to suggest that object oriented programs make it easier to create logical errors and emergent bugs.
So, that's why I completely dismiss it, it fraudulently attempts to champion Rust as an obvious replacement of anything. For those who think this has something to do with Rust specifically, no, we've held these reservations for promised replacement languages for decades now. There is no evidence Rust's borrow checker alone has overcome enough of the problems of any previous example.
A short criticism of Rust is, for a supposed systems language replacement, they let far too many features and first party magic (cargo) into the language.
Generally speaking, the purpose of a program is not to minimize the number of memory safety bugs. All other things being equal, yes, having fewer memory safety bugs is better than having more. But perhaps you're trading legible bugs for illegible bugs? The rust implementation is most likely going to be more complex than the c implementation (which is fair since it almost eliminated a whole class of bugs), and in that complexity there is extra room for non-memory safety related bugs.
There's probably also 500x more people who know c to a given level then know rust to a given level.
If we have an analyzer that can find memory safety bugs in C, we could also just put that in the CI pipeline, or as a pre-submit hook before you're allowed to add code to a code base.
To be honest I feel like "this code is easier to review and less likely to require rollbacks" is even more of a valuable take from this article, just in terms of "hey, don't you like it when things don't have to be rolled back?"
Security issues are like bad etc too, just we've heard the security spiel so many times at this point. I just think it's nicer to write most stuff in Rust.
Yes, Rust's strictness makes it a lot more maintainable. It is so much more common that changing the one thing you wanted to change results in a compiler error at every single other site you need to change, without having to look at other areas of the codebase at all, and all the tests pass on the first try.
I don't know much about how it got started. I'm curious how much of Rust's capabilities depend upon recent CS breakthroughs. Could we have made Rust in 1990?
The compiler is also relatively slow. Would Rust have been worth working with on 30+ year old hardware?
Yeah, I am blown away. Assuming that these stats are true/verifiable, this spells real doom for C++. What is the point of C++ in 2025 except to maintain a large, existing source code base? Else, you should be doing everything that you used to do in C++ in Rust.
> What is the point of C++ in 2025 except to maintain a large, existing source code base?
Half of useful things to do are impossible or plain cumbersome to write in rust given the semantics and constraints of the borrow checker. Try to write self referential structures in rust and you'll have a more nuanced opinion.
Note that N=1 for the memory safety vulnerabilities they had with Rust, so the error of the estimated average number of vulnerabilities per LOC is quite large.
Large C++ codebases have the same problems that large codebases have in any language: too many abstractions, inconsistent ways of doing things, layers of legacy. It comes with the job. The difference is that in C/C++, hard-to-read code also means hard-to-guess pointer lifetimes.
They found a memory safety bug in their Rust code and assumed it was the only memory safety bug in their Rust codebase. And then they compared it to the historical average in C++ code that's been around for almost two decades in production. I can't be the only one here who sees how biased this comparison is right?
Rather, they found one memory safety bug in their Rust codebase, and measured it against the legions of memory safety bugs they found in their C++ codebase. In neither case are they measuring against bugs not found, so no, it's not biased.
If you want something more comparable, they estimate that only 5% of their Rust code is within unsafe blocks. That makes only 5% of the code with potential for memory safety issues: that's already a 20x improvement. Let's make it 10x because unsafe blocks tend to be trickier, but you still get a lot of Rust guarantees.
The thing is with Rust, you know where to look for memory safety issues: the unsafe blocks. C and C++? GLHF that's your whole codebase. As they mentioned, you don't opt-out of all of Rust guarantees by going the unsafe route. Of course you can ditch them, but that'll be hugely visible during code review. Overall, you can be much more confident saying "yup there's no bug there" in Rust than in C or C++.
Even if they are off by a factor of 100 it's a huge win and the point stands.
It's fair to point this out and worth the mention. Still, I'd like to think that the engineers behind this can at least gauge the benefit of this endeavor with some accuracy despite the discrepancy in available data, and stating the data that is available only makes sense.
and they found 1000 memory safety bugs and assumed it was the only 1000 memory safety bugs in that code which have been in production for 2 decades. How naive can they be?
Further up they refer to Android C/C++ code, not C/C++ in general:
"We adopted Rust for its security and are seeing a 1000x reduction in memory safety vulnerability density compared to Android’s C and C++ code."
Which means they had a pretty poor code base. If they had spent more time on engineering and less time on features that are canceled after 12 months anyway, they could have written better C/C++.
I peruse Android system code at work and their C++ code base is not designed for safety. It’s just typical C++ code as any large company would write it.
And for a large juicy target like Android, that won’t be good enough to stay ahead of the attackers long term.
Of course, tools like Fil-C or hardware-based security might make Rust vs. C or C++ moot.
Edit: your comment makes a good point. Shame that trigger-happy (c)rustaceans are downvoting everything in sight which is not praising this PR piece disguised as a technical blogpost.
Rust has been such a "pain" to learn - at least compared to other, more straight-forward languages. But boy does it feel good when you know that after a few back and forths with the compiler, the code compiles and you know, there is not much that is going to go wrong anymore.
Of course, I am exaggerating a bit - and I am not even that experienced with Rust.
But after coding with Ruby, JS/TS and Python - it feels refreshing to know that as long as your code compiles, it probably is 80-90% there.
Rust is the most defect-free language I have ever used.
I'd wager my production Rust code has 100x fewer errors than comparable Javascript, Python, or even Java code.
The way Result<T,E>, Option<T>, match, if let, `?`, and the rest of the error handling and type system operate, it's very difficult to write incorrect code.
The language's design objective was to make it hard to write bugs. I'd say it succeeded with flying colors.
> Rust has been such a "pain" to learn - at least compared to other, more straight-forward languages. But boy does it feel good when you know that after a few back and forths with the compiler, the code compiles and you know, there is not much that is going to go wrong anymore.
I found that at some point, the rust way kinda took over in my head, and I stopped fighting with the compiler and started working with the compiler.
One big source of bugs in TS is structural sharing. Like, imagine you have some complex object that needs to be accessed from multiple places. The obvious, high performance way to share that object is to just pass around references wherever you need them. But this is dangerous. It’s easy to later forget that the object is shared, and mutate it in one place without considering the implications for other parts of your code.
I’ve made this mistake in TS more times than I’d like to admit. It gives rise to some bugs that are very tricky to track down. The obvious ways to avoid this bug are by making everything deeply immutable. Or by cloning instead of sharing. Both of these options aren’t well supported by the language. And they can both be very expensive from a performance pov. I don’t want to pay that cost when it’s not necessary.
Typescript is pretty good. But it’s very normal for a TS program to type check but still contain bugs. In my experience, far fewer bugs slip past the rust compiler.
Not parent comment, but TS is generally safe if you have types correct at system borders, but very scary when you don't. Some of the most impactful bugs I've seen are because a type for an HTTP call did not match the structure of real data.
Also, many built in functions do not have sufficient typesafey like Object.entries() for instance
Typescript doesn't even support notions like "unsigned integer". It is not a serious attempt at type-safety; its main claim to fame is "better than raw Javascript" which is not saying much.
Note that Google still doesn't have official support for using Rust in Android userspace, though.
Despite all pluses on the blog, NDK only supports C and C++ tooling, same on Android Studio, and it is up to the community to do the needful work, if anyone feels like using Rust instead.
Nobody's stopping you from using the NDK to compile Rust though. Android's ABI is just an ABI like any other. The system doesn't care if you built an .so using Rust or anything else so long as it plays by the rules.
The thing about Rust is you pay for everything up front, and the dividends come later. You pay first to learn it, which is not easy. Then you pay every time you have to compile your code, which can kill development momentum. When you are learning, often times this manifests as a moment where you have to completely rearchitect your approach because plowing forward is too costly. It's at this point a lot of people say "Rust is too hard!" and they give up.
But if you stick it out, as Google has, the dividend is that more often than with other languages, you are not paying these costs continually but instead reaping dividends on the long run.
First of all, Rust has the Haskell-like property that (as long as the logic is sound) if your code compiles, it usually runs just fine. This is why testing speeds up, because all of the edge cases that are explored during testing were already accounted for by the compiler.
It also translates into easier refactoring, where you can make sweeping changes in the codebase and feel confident that you can put it all back together again.
And then there's the fact that the programs themselves are fast. How many times has uv been brought up here and the #1 remark people have is "wow it's so fast!". Fast is a feature, and your users benefit from it every time they run your code.
It's hard to find that nexus of features in other languages. Usually they are just as fast and hard to write as Rust, without the safety guarantees. Or they are just as safe as Rust, but without the speed. And that's why Rust has hit a sweet spot where other languages can't quite get it.
It's so easy to bake in proofs/invariants into types, yet you still retain control of the memory model.
One of the main features of Rust is the community, there are so many great packages
Something that will replace/build on Rust in the future is a language based on Two Level Type theory, where you have zero cost abstractions with a language that can do full dependent type theory
I agree with you as long as you don't know C++ first. I actually teach C++ and Rust to students who only know Java, and they have a much easier time picking up Rust. It's the people who approach Rust with C++ idioms who have the wort time with it. It comes down to the tooling, especially Cargo being the one-stop-shop for everything Rust. Another poster here laments that Cargo is too overloaded with disjoint functionality, but that's actually a benefit for a lot of learners.
C++ is the hardest, most difficult programming language to write correct (according to spec, not in the ‘it compiles’ sense) programs in ever created that isn’t a toy or specifically designed to be hard like malbolge. It takes a decade of writing it daily to realize that you know nothing, precisely because the compiler does not reject so many invalid programs.
>if your code compiles, it usually runs just fine.
This was the same argument for Java, which is memory safe, fairly strict in terms of ownership.
The fact is, Rust addresses only one memory safe thing, and that is double free. If you don't understand why that is, you probably shouldn't talk about memory safety.
The dividends never get there if you don't ever run into this.
>And then there's the fact that the programs themselves are fast. How many times has uv been brought up here and the #1 remark people have is "wow it's so fast!"
This is a vibe at best. The speed difference is surely there. But it makes very little difference when there are much slower things in the entire workflow, like pulling things from the internet.
Basically, Rust is a good choice for a small subset of things. Android happens to be one of them, because a) you need native code performance, b) you have multiple teams working on many services and c) you have a somewhat closed ecosystem where you control a lot of the low level things. Because of all of this, double frees are a real threat and can pop up as you are passing data around without strict checks.
> The fact is, Rust addresses only one memory safe thing, and that is double free. If you don't understand why that is, you probably shouldn't talk about memory safety.
Have fun justifying that Rust is "also" unsafe, with the right tools you can achieve the same in C++, if you're a great dev you can do even better, etc.
rust has other advantages. I think cargo is better than cmake. I think the syntax is better, I think the way dependencies and modules are handled is better.
It can be annoying to write "safe" code, but once it meets a certain standard I can be confident in multithreaded applications I write.
I would like to use rust to write android apps. I don't really like the whole android studio java thing.
I expect that Google is using neither of these for most of their own code, but rather their own build system (which I think is the same between the languages).
That is an understatement. I can't think of a build system that has spawned more attempts to find something better than CMake has.
There have been so many people trying to make their own C/C++ build system and/or package manager out of sheer spite for CMake that it's frankly hard to keep track.
In fairness to them and to CMake, it's not a simple problem to solve. To truly know CMake is to wish you didn't, that way someone else would have to maintain it.
For me the ideal syntax is C/Go, just to be clear what I like.
But I agree that the tooling that cargo introduced is a breath of fresh air in a world dominated by huge makefiles, libraries copied in the repository (I know, there is Conan, vcpkg etc)...
Cargo is absolutely awful. It might be better than cmake, but it still the worst part about Rust. It’s completely opaque, and intermixes a huge pile of different functionality.
Distributing Rust software is the pain that it is mostly because of how Cargo works. It’s pretty much impossible to sanely distribute something that isn’t a headache for downstream to consume.
The only people I’ve met who seem to think it’s a feud war are a few dyed in the wool C++ fans who implicitly hate the idea of programming anything else. Rust is just a language. It has some strengths and weaknesses just like every programming language. Some of its strengths are incredibly compelling.
Personally I’m relieved that we’re starting to see real competition to the C & C++ duopoly. For awhile there all the new languages were GC, and paid for their shiny features with poor runtime performance. (Eg java, C#, Ruby, Python, lua, go, etc etc)
Rust is a fine language. Personally I can’t wait to see what comes after it. I’m sure there’s even better ways to implement some of rust’s features. I hope someone out there is clever enough to figure them out.
I mean we know for sure Rust is unsafe there is whole bug tracker dedicated to all the ways it's unsafe. My favorite is that you can cast any lifetime to static no matter how short it actually is in 100% safe Rust.
I think referencing the well-known cases in cve-rs[1] is quite a bad faith effort. Of course if you try reeeally hard to write unsound code, you can write unsound code. An edge case in the type system downstream of lifetime variance rules is simply not something that matters in any practical attempt to write safe software. I find the tracker interesting since it probes the boundary of the compiler, but it says absolute nothing to the effect of "Rust is unsafe".
The unsound bug tracker is were my heart gets all warm and fuzzy in Rust land.
All the ways to coerce and poke the implementation of what should be safe constructs to produce unexpected garbage - and people spending time fixing the issues because they are treated as bugs.
It’s like the best possible advertisement for ”we enable soundness and correctness for all your programs.”
This doesn't 'cast' anything. The compiler prevents this because it would allow references that outlive their owners. Freely 'casting' only works for data that is static in nature anyways, at which point a coercion is taking place. Any other way involves `std::mem::transmute` or `Box::leak` and the like.
Id like to see dev time in Rust vs C++, but generally, I sort of agree. If you use modern C++ with all its features, Rust is generally a better alternative.
That being said, it would be pretty easy to implement some pointer semantics even in C that can do 95% of what Rust does.
> That being said, it would be pretty easy to implement some pointer semantics even in C that can do 95% of what Rust does.
Making a language with memory-safe pointers isn't hard. Making a language with memory-safe pointers that doesn't rely on sandboxing, a virtual machine, or other dynamic checks which produce runtime overhead--thereby disqualifying one from being considered for this domain in the first place--is nontrivial.
And tell me how that pointer semantics would do
* a very strict type checking
* Pattern matching
* Algeberic data type
Plenty of people don't write Rust for additional memory safety, they write Rust because the features provided by it is overall very balanced & encourages developer to write code which handles almost all edge cases.
The issue with most codebases is nobody thinks about starting out with acceptance testing system.
The way it should work is that before even writing code, you design a modular acceptance system that runs full suite of tests or a subset based on what you are working on.
This is essentially your contract for software. And on a modular level, it means that it scopes down the contracts to the individual sub systems. And things like memory and cpu runtime constraints are a part of this.
If you have this, you basically replace what the Rust compiler is doing for you with tests. Memory leaks are caught. However, as a benefit, you also can verify changes in the dev cycle with things like performance degradation, all in the same system.
I'm not sure that nobody thinks of this. We just have a finite amount of time. Usually with a solid approach, you get solid performance. Fixing a performance related bug rarely when it comes up, is still a time savings over designing this kind of rigorous process from scratch, and getting everyone on board with it.
Getting rid of a whole host of bugs due to the compiler is a big deal because you won't have to design this extra acceptance system or deal with keeping an entire organization disciplined by it. If you can solve this seamlessly I think that's an interesting product that others would be very interested in.
> The way it should work is that before even writing code, you design a modular acceptance system that runs full suite of tests …
Sometimes. It depends on what you’re working on.
Part of the fun challenge in writing software is that the act of programming can teach you that you’re wrong at every level. The syntax can be wrong. The algorithm you’re implementing can be wrong. The way you’re designing a module can be misguided. And you might be solving the wrong problem entirely! Like, maybe you spend weeks adding a feature to a game and it makes the game less fun! Oops!
Tests formalise beliefs about what you want your code to do, at some level of abstraction. But if those beliefs turn out to be wrong, the tests themselves become a headwind when you try and refactor. You want those early refactoring to be as easy as possible while you’re learning a problem space.
Now, some programs don’t suffer from this as much. If you’re implementing a C compiler or drop in replacement for grep, you have some clear acceptance tests that will almost certainly not change through your project’s lifecycle.
But not all problems have clear constraints like that. Sometimes you’re inventing a programming language. Or writing a game. Or making a user interface. In my opinion, problems that are fully constrained from the start are some of the least interesting to work on. Where’s the discovery?
I will simply say that Google is one of the few places that, to a first approximation, has this. We have our (pretty good) suite of tests. We can run only affected tests. We can them with instrumentation (*SAN), we can run them under various memory and CPU limits, we can run them 1000 times in parallel to deflake.
Anyway Google has all of that, and yet still finds this improvement.
Writing the tests before the code only really works if there's an interface that's fully defined and well specified in advance. There are definitely times where that is the case, but in my experience it usually doesn't work like that.
Funny, another commenter on this post was saying the opposite, that Rust was likely being used to just port existing features and that was easier because there were probably good tests for it already.
If you've actually written considerable amounts of Rust and C++, these statistics don't require justification. In my opinion it's completely expected that Rust code is easier to write correctly.
For example: folks are more likely to rewrite stuff that is well-understood, and stuff that is well-understood is going to have shorter review times and lower rollback rate.
That gnarly horrid mess that only a few greybeards grok and has massive test coverage, a long tail of requirements enforced by tests and experience, and a culture of extreme rigor? Longer reviews, more rollbacks, and less likely to be rewritten.
The first chart does in fact a compelling reason to believe the effect is not that at all. If the "easy" code was predominantly being rewritten you would expect to % new memory unsafe code and % memory safety vulnerabilities to scale at different rates as the difficult to work on areas remained in C and kept causing new memory vulnerabilities.
Personal experience also provides a compelling reason, my experience is absolutely that people are more inclined to rewrite the things that are causing trouble in a new language.
It's not a blinded randomly controlled trial of course, it's observational data. You can't be completely sure there isn't a confounding factor that explains the data, but it seems far more likely than not that it is a real effect.
> That gnarly horrid mess that only a few greybeards grok and has massive test coverage, a long tail of requirements enforced by tests and experience, and a culture of extreme rigor? Longer reviews, more rollbacks, and less likely to be rewritten.
I'd say that this is likely the most likely to be rewritten actually, because high test coverage is a massive enabler in such a rewrite, and because having a project that “only a few greybeards grok” sounds like a big organizational liability.
That being said, and while I'm pretty convinced that Rust bring massive benefits, I agree with you that these measurements shouldn't be taken as if it was a rigorous scientific proof. It's more of one additional anecdotal evidence that Rust is good.
This, from my limited experience working on AOSP at Google, only the newer code were being written in Rust, not the existing code. But that was 2 years ago.
> Chromium: Parsers for PNG, JSON, and web fonts have been replaced with memory-safe implementations in Rust, making it easier for Chromium engineers to deal with data from the web
I find this surprising, isn't Wuffs[1] (also made by Google) an even better fit for this particular use-case? (It has compile-time spatial memory safety, where Rust has compile-time temporal safety but runtime spatial safety, with bound checking).
Obviously for general-purpose system programming, Rust is a no-brainer and I'm happy to see Google pursuing their rustification of Android.
I don't find it surprising, just from barriers to adoption: "Wuffs programs take longer for a programmer to write, as they have to explicitly annotate their programs with proofs of safety" is a hard sell (even if it has obvious value) and "you have to learn and integrate yet another language just for parsing files" is a hard sell too.
Which isn't to say that it shouldn't be adopted (having not used it I really don't know), just that it's not surprising that it's having difficulty gaining traction.
If you're parsing untrusted data, then some level of runtime checking is unavoidable. And Rust's pretty good at letting you encode "I already checked this and therefore don't need to check it again" into the type system.
Rust is good, don't get me wrong, but bound checks are still reason why you occasionally need unsafe to get the maximum performance, because not everything can be expressed as an iterator where bound checks are automatically eliminated.
If you check Wuffs repo, you'll see benchmarks very favorably comparing to rust implementations.
And it's not surprising, wuffs is to spatial safety what the borrow checker is to temporal safety. And regarding spatial safety rust is kind of like where C++ is in terms of temporal safety: it has the choice between unsafe or runtime check hopping that a large fraction of them will get eliminated by the compiler.
And I say this as someone who has never written a line of Rust in their life (some day I'll find the time).
On one hand, C++ is an incredibly complicated language that one can invest considerable amounts of time into. It also used to occupy a unique niche where you get tons of abstraction features yet as much blazing speed as you care to spend time optimising. Rust is encroaching on that niche.
On the other hand, C is an incredibly simple language, which does not allow for convenient expressions of particular abstractions. If they hated C++ because it was too hard to follow. What the code is doing, they probably hate rust for the similar levels of abstraction affordances.
When I hear the bad faith arguments from people who really should know better, what I hear is a group of scared developers who have been able to coast on their knowledge base for years or even decades, and are now feeling like their skill set is at risk of being unnecessary.
It always seemed like an unproductive attitude to have in a knowledge-based industry like software development. I am also a C++ developer, but you bet I am learning Rust on the side, because I think it's a good idea to skate where the puck is headed. I also learned enough of Zig to be dangerous a few months ago because it was fun.
Either way, I would suggest those developers reflect on the reason why they have this reflexive need to throw a wrench into any conversation mentioning rust. If their intention is to slow down adoption through hostile community sentiment, it's not working.
We're decades into the global warming era. You simply can't make some people accept evidence if the conclusions from that evidence would be uncomfortable to them.
If people don't take exploitability seriously, you can't make them. Well, unless you keep pwning them.
[0]: Or even whole-assed. Memory (un)safety is only one form of vulnerability.
That said, memory safety is one criterion out of many that could be used to make that decision. For a large number of software projects, memory safety simply isn't a major concern. Ease of use, iteration speed, developer familiarity, availability of specific libraries, and so on, are often equal or greater concerns than memory safety.
So, sure, if you're writing a kernel, operating system, or a mission-critical piece of software, then Rust might be worth considering. Otherwise, you might be better served by other languages.
Because it's not a silver bullet. That safety comes at a cost; Rust is much more difficult to learn than C or Zig and the compilation time for code with equivalent semantics is an order of magnitude greater. It has also added a great deal of toolchain complexity to projects like the Linux kernel.
People have decided that the pros outweigh the cons in those particular cases, but those cons exist nonetheless.
Dead Comment
Nah. For me it induces vomit. Any time the vulnerability is mentioned a horde will arrive promptly and sing "rewrite the ... " in Rust.
For fuck's sake. We got it. We know it is mostly memory safe with bunch of other protections baked in. So go and rewrite it and then try to sell it to your customer and have them pay for this job. If you succeed - congrats, good for you and for the "victims". If not - stop nagging people who have other things to worry about.
So, that's why I completely dismiss it, it fraudulently attempts to champion Rust as an obvious replacement of anything. For those who think this has something to do with Rust specifically, no, we've held these reservations for promised replacement languages for decades now. There is no evidence Rust's borrow checker alone has overcome enough of the problems of any previous example.
A short criticism of Rust is, for a supposed systems language replacement, they let far too many features and first party magic (cargo) into the language.
There's probably also 500x more people who know c to a given level then know rust to a given level.
If we have an analyzer that can find memory safety bugs in C, we could also just put that in the CI pipeline, or as a pre-submit hook before you're allowed to add code to a code base.
Security issues are like bad etc too, just we've heard the security spiel so many times at this point. I just think it's nicer to write most stuff in Rust.
The compiler is also relatively slow. Would Rust have been worth working with on 30+ year old hardware?
Half of useful things to do are impossible or plain cumbersome to write in rust given the semantics and constraints of the borrow checker. Try to write self referential structures in rust and you'll have a more nuanced opinion.
They compare something new, which rewrite existing stuff (not only but still) with some decades-years-old cruft
In they new code, they know what they want
They can also start with state-of-the-art unit testing that may not exist in the early 2000
So .. yeah, those numbers ..
That rust is saner than c++ is a given anyway :)
Large C++ codebases have the same problems that large codebases have in any language: too many abstractions, inconsistent ways of doing things, layers of legacy. It comes with the job. The difference is that in C/C++, hard-to-read code also means hard-to-guess pointer lifetimes.
To a degree that users might want to even exploit such flaws to unlock their phones.
Aside from that. Sure, the constraints of Rust do solve these kinds of problems.
The thing is with Rust, you know where to look for memory safety issues: the unsafe blocks. C and C++? GLHF that's your whole codebase. As they mentioned, you don't opt-out of all of Rust guarantees by going the unsafe route. Of course you can ditch them, but that'll be hugely visible during code review. Overall, you can be much more confident saying "yup there's no bug there" in Rust than in C or C++.
It's fair to point this out and worth the mention. Still, I'd like to think that the engineers behind this can at least gauge the benefit of this endeavor with some accuracy despite the discrepancy in available data, and stating the data that is available only makes sense.
"We adopted Rust for its security and are seeing a 1000x reduction in memory safety vulnerability density compared to Android’s C and C++ code."
Which means they had a pretty poor code base. If they had spent more time on engineering and less time on features that are canceled after 12 months anyway, they could have written better C/C++.
And for a large juicy target like Android, that won’t be good enough to stay ahead of the attackers long term.
Of course, tools like Fil-C or hardware-based security might make Rust vs. C or C++ moot.
Edit: your comment makes a good point. Shame that trigger-happy (c)rustaceans are downvoting everything in sight which is not praising this PR piece disguised as a technical blogpost.
Of course, I am exaggerating a bit - and I am not even that experienced with Rust.
But after coding with Ruby, JS/TS and Python - it feels refreshing to know that as long as your code compiles, it probably is 80-90% there.
And it is fast, too.
All that fighting with the compiler is just fixing runtime bugs you didn’t realize were there.
I'd wager my production Rust code has 100x fewer errors than comparable Javascript, Python, or even Java code.
The way Result<T,E>, Option<T>, match, if let, `?`, and the rest of the error handling and type system operate, it's very difficult to write incorrect code.
The language's design objective was to make it hard to write bugs. I'd say it succeeded with flying colors.
I found that at some point, the rust way kinda took over in my head, and I stopped fighting with the compiler and started working with the compiler.
I’ve made this mistake in TS more times than I’d like to admit. It gives rise to some bugs that are very tricky to track down. The obvious ways to avoid this bug are by making everything deeply immutable. Or by cloning instead of sharing. Both of these options aren’t well supported by the language. And they can both be very expensive from a performance pov. I don’t want to pay that cost when it’s not necessary.
Typescript is pretty good. But it’s very normal for a TS program to type check but still contain bugs. In my experience, far fewer bugs slip past the rust compiler.
Also, many built in functions do not have sufficient typesafey like Object.entries() for instance
Deleted Comment
Despite all pluses on the blog, NDK only supports C and C++ tooling, same on Android Studio, and it is up to the community to do the needful work, if anyone feels like using Rust instead.
The point is about the official support for using Rust exactly for the same use cases.
Deleted Comment
But if you stick it out, as Google has, the dividend is that more often than with other languages, you are not paying these costs continually but instead reaping dividends on the long run.
First of all, Rust has the Haskell-like property that (as long as the logic is sound) if your code compiles, it usually runs just fine. This is why testing speeds up, because all of the edge cases that are explored during testing were already accounted for by the compiler.
It also translates into easier refactoring, where you can make sweeping changes in the codebase and feel confident that you can put it all back together again.
And then there's the fact that the programs themselves are fast. How many times has uv been brought up here and the #1 remark people have is "wow it's so fast!". Fast is a feature, and your users benefit from it every time they run your code.
It's hard to find that nexus of features in other languages. Usually they are just as fast and hard to write as Rust, without the safety guarantees. Or they are just as safe as Rust, but without the speed. And that's why Rust has hit a sweet spot where other languages can't quite get it.
It's so easy to bake in proofs/invariants into types, yet you still retain control of the memory model.
One of the main features of Rust is the community, there are so many great packages
Something that will replace/build on Rust in the future is a language based on Two Level Type theory, where you have zero cost abstractions with a language that can do full dependent type theory
This was the same argument for Java, which is memory safe, fairly strict in terms of ownership.
The fact is, Rust addresses only one memory safe thing, and that is double free. If you don't understand why that is, you probably shouldn't talk about memory safety.
The dividends never get there if you don't ever run into this.
>And then there's the fact that the programs themselves are fast. How many times has uv been brought up here and the #1 remark people have is "wow it's so fast!"
This is a vibe at best. The speed difference is surely there. But it makes very little difference when there are much slower things in the entire workflow, like pulling things from the internet.
Basically, Rust is a good choice for a small subset of things. Android happens to be one of them, because a) you need native code performance, b) you have multiple teams working on many services and c) you have a somewhat closed ecosystem where you control a lot of the low level things. Because of all of this, double frees are a real threat and can pop up as you are passing data around without strict checks.
How does Rust not address use after free?
Have fun justifying that Rust is "also" unsafe, with the right tools you can achieve the same in C++, if you're a great dev you can do even better, etc.
It can be annoying to write "safe" code, but once it meets a certain standard I can be confident in multithreaded applications I write.
I would like to use rust to write android apps. I don't really like the whole android studio java thing.
I expect that Google is using neither of these for most of their own code, but rather their own build system (which I think is the same between the languages).
I absolutely agree if you aren't Google though.
That is an understatement. I can't think of a build system that has spawned more attempts to find something better than CMake has.
There have been so many people trying to make their own C/C++ build system and/or package manager out of sheer spite for CMake that it's frankly hard to keep track.
In fairness to them and to CMake, it's not a simple problem to solve. To truly know CMake is to wish you didn't, that way someone else would have to maintain it.
For me the ideal syntax is C/Go, just to be clear what I like.
But I agree that the tooling that cargo introduced is a breath of fresh air in a world dominated by huge makefiles, libraries copied in the repository (I know, there is Conan, vcpkg etc)...
Distributing Rust software is the pain that it is mostly because of how Cargo works. It’s pretty much impossible to sanely distribute something that isn’t a headache for downstream to consume.
Personally I’m relieved that we’re starting to see real competition to the C & C++ duopoly. For awhile there all the new languages were GC, and paid for their shiny features with poor runtime performance. (Eg java, C#, Ruby, Python, lua, go, etc etc)
Rust is a fine language. Personally I can’t wait to see what comes after it. I’m sure there’s even better ways to implement some of rust’s features. I hope someone out there is clever enough to figure them out.
Then there are enough industry standards that are defined for C and C++, where Rust isn't even visible.
Deleted Comment
(doesn't mean it's not an improvement on C++)
[1] https://github.com/Speykious/cve-rs
All the ways to coerce and poke the implementation of what should be safe constructs to produce unexpected garbage - and people spending time fixing the issues because they are treated as bugs.
It’s like the best possible advertisement for ”we enable soundness and correctness for all your programs.”
https://github.com/rust-lang/rust/issues?q=state%3Aopen%20la...
That being said, it would be pretty easy to implement some pointer semantics even in C that can do 95% of what Rust does.
Making a language with memory-safe pointers isn't hard. Making a language with memory-safe pointers that doesn't rely on sandboxing, a virtual machine, or other dynamic checks which produce runtime overhead--thereby disqualifying one from being considered for this domain in the first place--is nontrivial.
Plenty of people don't write Rust for additional memory safety, they write Rust because the features provided by it is overall very balanced & encourages developer to write code which handles almost all edge cases.
Which is more that rust isn’t that safe in my mind, it’s that bugs are that prevalent. I never would have guessed that.
That 4x rate is very impressive too.
Great seeing all this data from a large big complicated codebase.
The way it should work is that before even writing code, you design a modular acceptance system that runs full suite of tests or a subset based on what you are working on.
This is essentially your contract for software. And on a modular level, it means that it scopes down the contracts to the individual sub systems. And things like memory and cpu runtime constraints are a part of this.
If you have this, you basically replace what the Rust compiler is doing for you with tests. Memory leaks are caught. However, as a benefit, you also can verify changes in the dev cycle with things like performance degradation, all in the same system.
Getting rid of a whole host of bugs due to the compiler is a big deal because you won't have to design this extra acceptance system or deal with keeping an entire organization disciplined by it. If you can solve this seamlessly I think that's an interesting product that others would be very interested in.
Sometimes. It depends on what you’re working on.
Part of the fun challenge in writing software is that the act of programming can teach you that you’re wrong at every level. The syntax can be wrong. The algorithm you’re implementing can be wrong. The way you’re designing a module can be misguided. And you might be solving the wrong problem entirely! Like, maybe you spend weeks adding a feature to a game and it makes the game less fun! Oops!
Tests formalise beliefs about what you want your code to do, at some level of abstraction. But if those beliefs turn out to be wrong, the tests themselves become a headwind when you try and refactor. You want those early refactoring to be as easy as possible while you’re learning a problem space.
Now, some programs don’t suffer from this as much. If you’re implementing a C compiler or drop in replacement for grep, you have some clear acceptance tests that will almost certainly not change through your project’s lifecycle.
But not all problems have clear constraints like that. Sometimes you’re inventing a programming language. Or writing a game. Or making a user interface. In my opinion, problems that are fully constrained from the start are some of the least interesting to work on. Where’s the discovery?
Anyway Google has all of that, and yet still finds this improvement.
If you've actually written considerable amounts of Rust and C++, these statistics don't require justification. In my opinion it's completely expected that Rust code is easier to write correctly.
Deleted Comment
For example: folks are more likely to rewrite stuff that is well-understood, and stuff that is well-understood is going to have shorter review times and lower rollback rate.
That gnarly horrid mess that only a few greybeards grok and has massive test coverage, a long tail of requirements enforced by tests and experience, and a culture of extreme rigor? Longer reviews, more rollbacks, and less likely to be rewritten.
Personal experience also provides a compelling reason, my experience is absolutely that people are more inclined to rewrite the things that are causing trouble in a new language.
It's not a blinded randomly controlled trial of course, it's observational data. You can't be completely sure there isn't a confounding factor that explains the data, but it seems far more likely than not that it is a real effect.
I'd say that this is likely the most likely to be rewritten actually, because high test coverage is a massive enabler in such a rewrite, and because having a project that “only a few greybeards grok” sounds like a big organizational liability.
That being said, and while I'm pretty convinced that Rust bring massive benefits, I agree with you that these measurements shouldn't be taken as if it was a rigorous scientific proof. It's more of one additional anecdotal evidence that Rust is good.
But that means it's likely to be the worst kind of science:
- Group of people agree that Rust is good. This is a belief they hold.
- Same group of people feel the need to search for argument that their belief is good.
- The group does "science" like this.
And then the rest of us have a data point that we think we can trust, when in reality, it's just cherry picked data being used to convey an opinion.
Deleted Comment
It would be interesting to group changes by line-deletions, say to indicate rewrites (and size of them)
I find this surprising, isn't Wuffs[1] (also made by Google) an even better fit for this particular use-case? (It has compile-time spatial memory safety, where Rust has compile-time temporal safety but runtime spatial safety, with bound checking).
Obviously for general-purpose system programming, Rust is a no-brainer and I'm happy to see Google pursuing their rustification of Android.
[1]: https://github.com/google/wuffs
Which isn't to say that it shouldn't be adopted (having not used it I really don't know), just that it's not surprising that it's having difficulty gaining traction.
If you check Wuffs repo, you'll see benchmarks very favorably comparing to rust implementations.
And it's not surprising, wuffs is to spatial safety what the borrow checker is to temporal safety. And regarding spatial safety rust is kind of like where C++ is in terms of temporal safety: it has the choice between unsafe or runtime check hopping that a large fraction of them will get eliminated by the compiler.