Maybe it isn't an edge case (although it should be) it also isn't `easy` in a non GC'd language, and a huge source of memory bugs.
I wouldn't say it makes the 'easy stuff hard' as much as the 'hard stuff appropriately difficult'.
Maybe it isn't an edge case (although it should be) it also isn't `easy` in a non GC'd language, and a huge source of memory bugs.
I wouldn't say it makes the 'easy stuff hard' as much as the 'hard stuff appropriately difficult'.
I say "basic" in quotes because once you factor in the concurrency, ownership and memory safety concerns that are optional in other languages, but mandatory in Rust, there really isn't a simple implementation of these structures that is provably correct anymore.
Rust isn't hard just for fun. It's hard because the code you've been writing for so long is actually bad and you've not been thinking it through appropriately. This is why we keep finding serious bugs in code that is decades-old, despite the belief that code so old must be well-tested by now.
I'm sure of one thing: we will find many and different bugs in decades old rust code one day, too. The problem with software is that it has code in it ;-)
I don't understand why this argument keeps coming up. Not all bugs are the same and when you make entire classes of bugs unrepresentable, that's a massive win, especially when they happen to be the class containing >60% of the highest severity bugs in C.
https://www.chromium.org/Home/chromium-security/memory-safet...
I think there is a strong argument to be made that if you need a lot of unsafe, Zig is going to be the safer language.
I could see that. Haven't used zig but it does look very nice.
> in many places where unsafe ends up required
Yes, I definitely agree. I was specifically referring to the boundary of safe rust. I don't know how much more or less safe unsafe rust is vs c, but I do know that safe rust is certainly safer than c.
Not comment should be read as argument or part of a debate for or against using Rust or any other memory safe language. I made the comment because I've seen tool after tool come about to end the scourge of bugs in software... and so far my unconscious, untrained ability to find new and spectacular ways to create bugs has exceeded the ability of the makers of bug prevention tools to stop me.
buffer overflows [0] [1], use after frees [2] [3], and other memory bugs [4] [5] [6] can appear in safe rust from unsound unsafe internals.
[0] https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-2887...
[1] https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000...
[2] https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3116...
[3] https://github.com/rustsec/advisory-db/blob/main/crates/cros...
[4] https://github.com/rustsec/advisory-db/blob/main/crates/toki...
[5] https://github.com/rustsec/advisory-db/tree/main/crates/
From the link you’re sharing
> Fortunately, they are context-sensitive library APIs that are not usually used in a way that the bugs can be triggered. Many of them require very specific interaction to trigger (e.g., partially consume an iterator and zip() it with another iterator) that is not likely to appear in their daily usage.
Here’s a concrete example that shows the difference between how different languages approach CVEs. Rust is not the only language affected by this TOCTOU bug (https://blog.rust-lang.org/2022/01/20/cve-2022-21658.html) but other languages finesse it by saying “all bets are off when you’re interacting with the filesystem”. Therefore no CVE for them, while Rust ends up looking insecure in the eyes of those who count CVEs.
What I’m saying is - don’t count CVEs without looking at the context and content of those CVEs. Don’t assume that some software is secure simply because they don’t file CVEs, because that’s an ostrich approach.
The CVEs are counted as they're memory issues (not only logical issues) that can technically surface in safe Rust code and are also considered UB in other languages (those which finesse other conditions to be "unspecified" instead of "undefined") too.
CVEs have rating systems to better interpret their relevance. Whether these ratings incorporate how easy it is to trigger or how practical the damage could be is subjective. They primarily report potential exploits, not a standard for judgement. All this nuance though was lost with the parent commenter claiming "zero memory bugs in safe rust".
> Don’t assume that some software is secure simply because they don’t file CVEs
I agree. This extends across all languages. Another warning to add is that high profile security bugs can still occur without memory safety issues (with wormhole/dao exploits being practical examples).
Neither of us agree with a blanket assertion that code written in Rust is flawless and free of bugs.
This can be easily disproved by looking at the bugs fixed in the Rust compiler and standard library, and looking at open soundness issues in the Rust issue tracker.
I think CVEs are useful in tracking the security of your code, but can’t be meaningfully compared between languages. Different languages and ecosystems have differing bars on what needs a CVE.
The important takeaway is that while Rust and Rust code in general aren’t perfect, they’re still substantially better than the alternatives. Better is hard concept to convey and get people to buy into. They see a couple of bugs and say “well, there’s bugs either way so what difference does it make”.
For higher level domains where unsafe isn't required and some runtime overhead is acceptable, I believe there's real cases to be made that Rust can be substantially better than the alternatives; Can prevent logical UAF with borrowing, bound checks may be mostly elided, enforced language level checks for nullability like Option<&T> and valid values in general like enums, explicit error handling, etc.
For lower level domains however, I'm not sure that argument is as easy. Anecdotally, I work almost exclusively on systems like databases, schedulers, allocators, and similar. There, memory efficiency is an explicit feature via tricks that either Rust's borrow checker really doesn't like or are very awkward to do with its unsafe APIs; Non-linear/concurrent object lifetimes, self-referential & intrusive data structures, and reinterpret casting being the big ones.
If rust code makes it harder to do those things, while also providing little (never none) benefit over the alternatives (for reference, both Zig & Rust have checked {integer ops, slice access, nullability}, sum types, metaprogramming, rich error combinators, etc.) then it's harder to make the claim Rust is substantially better.
That said, your concerns are pretty valid, widely echoed and are being taken seriously. Writing unsafe code is a chore and it needn't be. I'm hoping the newly created Operational Semantics team (https://www.rust-lang.org/governance/teams/lang#Operational%...) makes progress here.
My point wasn't that rust is bug-free, but that certain classes of bugs will not exist in the safe portion, which significantly reduces attack surface.
Additionally, my point was to compare languages without safety guarantees like C to safe rust. Your statement is true, but it doesn't do anything to counter what I'm saying, which is that entire classes of bugs (namely the most common critical c bugs) are not found in safe rust, which is still the case.
Worded another way, within the boundaries of safe rust, you will not find a cause of a memory corruption bug. Things that can be the cause memory bugs include: unsound unsafe rust, c, kernel-level manipulation, random bit flips, malicious hardware, etc etc. I consider none of those to be bugs in safe rust, and additionally, they can cause bugs in all other programming languages as well.
I believe the tradeoff for this in Rust’s niche is absolutely acceptable, but it is still a tradeoff and might not be the correct choice in certain cases.
Sometimes Rust makes things hard because the invariants you want to express cannot be cleanly mapped onto Rust's type system. I described one such case here: https://blog.reverberate.org/2021/12/19/arenas-and-rust.html