Earlier quoted context omitted.
I think the comparison should be more nuanced and holistic than only memory safety, if it is to be a discussion on security and not theater. For example, to get the conversation started, how do both languages compare in terms of checked integer arithmetic? Do they enable checked arithmetic by default in safe builds with an opt-out for performance, or do they leave default builds unsafe with an opt-in for safety? Anot…
> All 100% memory safety, and yet security is still a thing. And nobody has ever claimed that memory safety is the only thing that matters with security, but it’s definitely high on the list. Can you imagine how much more of a nightmare NPM would be if JavaScript weren’t memory safe? This is the relevant counterfactual. > Zig is an order of magnitude safer than C, much closer to Rust actually, and more so in some are…
See HeartBleed, CloudBleed, all buffer underflows resulting in buffer bleeds, letting someone read all your sensitive server memory, with no UAF.
They can also be caused just by integer overflow, which is what makes unchecked integer arithmetic so incredibly dangerous. It's easy for programmers to be oblivious to this, and overly rely on the borrow checker, thinking it can provide 100% memory safety, when by definition it can't.
And all kinds of software systems have these vulnerabilities. For example, I've worked on static analysis security software that could detect bleeds automatically in outgoing email attachments and it would find different bank systems leaking data in autogenerated statements.
From this experience, and from some bug bounty and security engagements I've done, I'm much more comfortable actually with Zig's approach to correctness and safety overall. I think the borrow checker is pretty awesome and has some serious muscle, but nevertheless Zig impresses me with its strict focus on explicitness, which I believe is the best approach still to eliminate these kinds of semantic gaps in general.
The borrow checker obviously can't protect you from bleeds (it can from some where static allocation is at play), but checked arithmetic would, or at least go pretty far — and again, it's about the spectrum, not the extreme.
It would be great for Rust to enable checked arithmetic by default for safety, with an opt-out for performance. Flipping this around would be a better default.