Memory Safety Absolutists
When seeing the title of this post, I bet in some people's minds, the first thought was "Rust devs!". This connection is not unfounded. Rust devs tend to be passionate about memory safety. Some of it, I'm sure, may have been caused by a classic language wars attitude: my language is better than yours, and here is why. I'm hoping, though, that most of the Rust devs, who say they care about memory safety, genuinely care about making software safer, and not just criticizing languages that compete with Rust.
The article, surprisingly, is not about Rust devs.
Until recently, most of the memory safety related discourse had a relatively simple basis, at least when considering non-GC, systems programming languages, like C, C++, Zig, and Rust. Rust aims to disallow compiling programs that may introduce memory safety issues (at a cost of sometimes disallowing a program that would have been safe), with an escape hatch in the form of unsafe that allows, among other things, dereferencing raw pointers. C and others leave ensuring memory safety to the programmer. The amount of help from the language differs, for example there is RAII and smart pointers in C++, or defer in Zig, but for the most part nothing stops you from violating memory access.
The situation today is a bit different with a new way to make C, C++, and in the future maybe also Zig, code memory safe: Fil-C. C and C++ code compiled with Fil-C will panic on invalid memory access, like out of bounds access, or use after free. It achieves it by combining GC and InvisiCaps - a way to track memory accessible by a pointer. Zig's author recently announced a new compilation mode for Zig inspired by Fil-C. Fil-C is a very interesting project and I sincerely hope it will succeed and at least some popular C and C++ projects will provide Fil-C compiled releases.
a new compilation mode for Zig inspired by Fil-C
In an ideal world both Rust programmers and C/C++/Zig programmers that care about memory safety would be happy that there are more ways to minimize memory safety vulnerabilities, but alas, we're not living in an ideal world and I can't shake the feeling a lot of the criticism towards Rust recently is disingenuous. If you read Fil-C's author opinions on Twitter, it's blatantly obvious that he dislikes Rust and I've seen him claiming Rust is a memory unsafe language because of ability to bypass some of the Rust guarantees when using unsafe. Andrew Kelley, Zig's author, seems to have a similar stance demonstrated in the fil compilation mode issue title: "introduce an actually memory safe (unlike Rust) compilation mode inspired by Fil-C". Meaning: Rust is unsafe and only Fil-C or Zig's "fil" compilation mode will deal with memory safety related vulnerabilities.
Fil-C's author opinions on Twitter
In discussions related to Rust and Fil-C, I've often seen a claim similar to: "if Rust folks really cared about memory safety, they would promote Fil-C and ditch Rust as Fil-C is safer, otherwise they just care about their new shiny language, and not memory safety". That includes Fil-C's author himself. I'm not sure about Andrew Kelley, but the issue title I mentioned earlier feels awfully close. These kinds of arguments are, in my opinion, ignoring reality, and feel like fanaticism and cult-like behaviour that often Rust devs are accused of.
If Fil-C was a drop in replacement with absolutely zero trade-offs, I would maybe partially agree with the sentiment, but it has trade-offs: it's ABI incompatible with non-Fil-C compiled programs, it may be a few times slower in some cases, and it introduces GC. None of these things is a deal breaker for some programs. A lot of programs you use daily could be a few times slower than they are, and you wouldn't even notice. A lot of them also don't link anything dynamically, so the ABI compatibility doesn't matter. But not every software program is a simple utility. There are lots of popular projects, where GC and ABI incompatibility are an issue and there is no way they would ever start using Fil-C like technology, or at least not in a current form. Crucially, the kind of programs that can't use Fil-C are often a good fit for Rust.
But Rust is unsafe, isn't it? It has unsafe after all! If you want to be that strict, or in other words, if you are a memory safety absolutist, that may well be true for you. I, and I hope most people, am more pragmatic than that. There is not a whole lot of data on how secure Rust really is in practice, but to my knowledge there hasn't been a lot of exploitable memory safety vulnerabilities in Rust software, and there are big projects with some data, like 5M+ LOC in Android:
With roughly 5 million lines of Rust in the Android platform and one potential memory safety vulnerability found (and fixed pre-release), our estimated vulnerability density for Rust is 0.2 vuln per 1 million lines (MLOC).
Our historical data for C and C++ shows a density of closer to 1,000 memory safety vulnerabilities per MLOC. Our Rust code is currently tracking at a density orders of magnitude lower: a more than 1000x reduction.
I'm sure these numbers would differ for other projects, but I think by now it is well established that, in practice, Rust minimizes the risk of introducing memory safety issues.
If you could choose a technology that prevents 99.9% of issues in 100% of programs or 100% of issues in 90% of programs, which one would you choose? I have no idea what are the real numbers, but you get the point. Thankfully, we don't have to choose one or the other, contrary to what some people would claim. I would hope that projects written in C/C++/Zig, that can accept the trade-offs, will be available as Fil-C compiled binaries, and software that can't, will be written in languages that either completely or mostly remove the risk of introducing memory safety vulnerabilities.
And I also think it is totally fine to use Rust even if you could use a GC language like Go or Fil-C. Memory safety absolutists would tell you that's not acceptable, although some of them seem to apply memory safety absolutism only when it comes to Rust, and not C, C++, or Zig, go figure. The thing is, programs that can be also written in GC powered languages, often don't need unsafe at all, and programs that need unsafe often couldn't have been using GC. In my experience, people that don't approach solving problem with total fanaticism, tend to consider trade-offs. For many of them, a very small risk of ever running into a severe memory safety issue, is outweighed by other language guarantees (like data races prevention), and other language features. What's more, remember the 1000 memory safety related vulnerabilities per MLOC? With Fil-C they become crashes. It's still better than introducing a security vulnerability issue, but that's quite a lot of crashes to fix. If we're in a realm of fearing relatively uncommon problems, it might be good to state that there were security vulnerabilities in the past that were enabled by an attacker being able to crash a program.
I will end this post saying that if someone cares so much about memory safety that even Rust's 0.2 vulnerabilities per 1M lines of code is not acceptable, I would sure hope they will be criticizing people, who compile YOLO C/C++ and non-fil Zig, as much, if not more, as Rust developers. After all, if you genuinely care about memory safety so strongly that even Rust is not safe enough for you, you wouldn't want to allow people to use even less safe alternatives, would you?
If you like this post please consider following me on Twitter.