Comment by guywithahat
2 days ago
I had that thought too; the author claims tor suffers from user free bugs but like, really? A 20 year old code base with a massive supportive following suffers from basic memory issues that can often be caught with linters or dynamic analysis? Surely there are development issues I'm not aware of but I wasn't really sold by the article
That can easily happen in C programs. Some edge case doesn't really happen, unless you specifically craft inputs for that, or even sequences of inputs, and simply no one was aware for those 20 years, or no one tried to exploit that specific part of the code. With C you are never safe, unless you somehow proved the code to be free of such bugs.
This is a bit of an exaggeration. Many types of bugs can also happen with Rust, and with you use unsafe or have some dependency that uses it, then also memory safety bugs. At the same time, it is possible to reduce the probability and impact of such bugs in C code in a reasonable way even without formal verification.
Does every discussion of Rust and C need this recurring subthread conversation? It is approaching Groundhog Day levels of repetition. Yes, `unsafe` code can have memory safety bugs. Yes, `unsafe` doesn't mean "unsafe". Yes, a sufficiently advanced C-developer can have a sufficiently advanced C-codebase with reduced probability of bugs that might be even better than an insufficiently advanced Rust-developer. Yes, regular safe-Rust isn't the same formal verification. Yes, Rust doesn't catch every bug.
On the other hand, most developers have no need of writing `unsafe` Rust. The same tools used for static and dynamic analysis of C codebases are available to Rust (ASAN and friends) and it is a good idea to use them when writing `unsafe` (plus miri).
The reason I'm replying is that "the impact of Rust on memory safety" is always a conversation that gets outsized amounts of ink that it drains focus away from other things. I would argue that sum types and exhaustive pattern matching are way more important to minimize logic bugs, even if they aren't enough. You can still have a directory traversal bug letting a remote service write outside of the directory your local service meant to allow. You can still have TOCTOU bugs. You can still have DoS attacks if your codebase doesn't handle all cases carefully. Race conditions can still happen. Specific libraries might be able to protect from some of these, and library reuse increases the likelihood of of these being handled sanely (but doesn't ensure it). Rust doesn't protect against every potential logic error. It never claimed to, and arguing against it is arguing against a strawman. What safe-Rust does claim is no memory safety bugs, no data races, and to provide language and tooling features to model your business logic and deal with complexity.
3 replies →
If a codebase is being maintained and extended, it's not all code with 20 years of testing.
Every change you make could be violating a some assumption made elsewhere, maybe even 20 years ago, and subtly break code at distance. C's type system doesn't carry much information, and is hostile to static analysis, which makes changes in large codebases difficult, laborious, and risky.
Rust is a linter and static analyzer cranked up to maximum. The whole language has been designed around having necessary information for static analysis easily available and reliable. Rust is built around disallowing or containing coding patterns that create dead-ends for static analysis. C never had this focus, so even trivial checks devolve into whole-program analysis and quickly hit undecidability (e.g. in Rust whenever you have &mut reference, you know for sure that it's valid, non-null, initialized, and that no other code anywhere can mutate it at the same time, and no other thread will even look at it. In C when you have a pointer to an object, eh, good luck!)