It’s pretty subtle, but I think it’s important to notice that here Rust is being fundamentally held to a higher bar (which is fair, to be clear).
The C vulnerabilities are basically all the case that on specific user input, they materialize.
The Rust vulnerabilities are “if you use this API in this particular way” they materialize. (This is also the case for a lot of the Python RCEs, the only way to trigger them is to execute arbitrary Python code.)
That’s a big advancement! Unless they’re in common patterns, the vulnerable code won’t actually be exploitable.
I think this observation is supported by real world evidence. Consider Domato, which is a DOM fuzzer for browsers. When Project Zero folks ran it for 100,000,000 iterations on each major browser, it found vulnerabilities in all of them. So far, when it’s been run against rust, it finds a bunch of panics, but not vulnerabilities as far as I can tell: https://github.com/servo/servo/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+domato
Rust should continue to aim higher: less need for unsafe, better abstractions for writing safe unsafe code, and clearer semantics for unsafe code. But I think it’s important to be clear that Rust has already significantly raised the bar.
You might miss the point of this article if you didn’t read to the end - essentially, all modern web browsers have so much messy C with so many bugs with security implications that they don’t have time to file CVEs for all of them. He argues that, though imperfect, Rust at least has a chance of fully replacing C and dramatically increasing safety in the software we use every day.
The piece links to this post, which is a fascinating deep dive into the implementation and bug fix/enhancement of a vector datatype meant to be especially performant in cases where its length is small (SmallVec), but was actually slower and unsound (remedied by the post’s author for both ills):
I don’t really understand the “and why you shouldn’t care” part of the title; there’s never another reference to why you shouldn’t care.
I think the “why you shouldn’t care” was in reference to Vec being just as fast in most use cases.
I can maybe see that, but when all was said and done, SmallVec was faster than Vec in the case that it was small enough and used such that it could be allocated on the stack, which was the motivating use case for its existence. That seems like something I would care about, if I had cared to try to optimize my code by using SmallVec instead of Vec. Its disadvantage over Vec in an application would likely be hard to localize without specific microbenchmarks, I’m betting, so the fact that it was counterproductive could easily have slipped by even if attention was being paid to performance overall.
I guess the very last sentences support your conclusion (“If you’re using smallvec for its performance benefits, it’s worth benchmarking your program using Vec with Vec::with_capacity instead. Usually the simpler implementation is the faster one.”) but I still think the headline is sub-optimal; you have to care enough to benchmark still! Regardless, the piece overall (as well as the OP) is still pretty great.