And fuzzing originated in C / C++ tools and is available for them as well, probably more diverse and mature than what is available in Rust.
The point you did ignore was: Rust is being sold as magically making software safe and people selling that completely ignore the fact that logical bugs are also a thing.
Which Rust evangelists find difficult to acknowledge because security is that one thing that Rust has going for it.
So difficult that you would rather try to misdirect than to acknowledge that software written in Rust will crash. And when processing arbitrary user output, it'll crash badly when not written with care and fuzzed a lot. Kind of like C++.
It didn't for them, that's why they rewrote it.
> Rust is being sold as magically making software safe and people selling that completely ignore the fact that logical bugs are also a thing.
By whom? I don't think memory safety bugs are the only class of bugs, and neither do you, so who are you arguing against?
> Which Rust evangelists find difficult to acknowledge because security is that one thing that Rust has going for it.
Hard disagree. Rust also offers a solid type system, pain-free dependency management and all-around good tooling, just to name a few. It's much more than a "memory-safe C++" or whatever.
> And when processing arbitrary user output, it'll crash badly
If your definition of "badly" is "at a well-defined point, without any memory corruption", sure. But even here memory safety prevents what could be a much more painful debugging experience.
But yes, my point was that there are a lot of enthusiastic articles about how Rust can prevent "whole classes of bugs", which mostly gloss over the fact that there are other classes of bugs that it doesn't prevent. Of course this doesn't mislead experienced developers, but I'm not so sure about novices or less technically inclined people.
That's nothing more than a technically-dressed version of whataboutism, isn't it? Or can you show other languages that do prevent those other unnamed classes of bugs?
Are you disappointed that Rust evangelists don’t spend time talking about the fact that bugs can exist in Rust programs? Did you see the two articles posted in the last week alone about bugs that were found in Rust code? They reached the front page of HN
- https://hacks.mozilla.org/2022/06/everything-is-broken-shipp...
- https://hacks.mozilla.org/2022/06/fuzzing-rust-minidump-for-...
If you want to see criticism of Rust, I’ve found that the most informed criticism comes from people who use Rust a lot. Example - https://matklad.github.io/2020/09/20/why-not-rust.html
It may well have, but the Rust version “was faster, it crashed less, and we even knew it fixed some issues”
https://hacks.mozilla.org/2022/06/everything-is-broken-shipp...
You know, I'm a Rust evangelist. And I can tell you, why I ignore logic bugs when trying to sell Rust. Rust can prevent some logic bugs if they break invariant you managed to encode or enforce in your types. But it is a difficult topic to dive in a internet discussion. The best I could do is to bring some anecdotal data points, like &str being guaranteed to contain only valid utf8 strings. The worse issue (for a discussion) that it may be not obvious what kind of a logic error can be fixed by the type invariant discussed. So to show it I need to find some more examples of bugs that were prevented by enforcing the invariant. But you see, bugs that were prevented were not documented. It goes like this: you write code, it doesn't compile because rustc is unhappy, you fix code and it compiles nice now, you call it a day and move along. When you fixed this small issue it was not a bug, just one of a several complaints of rustc. You would need to speculate a lot about what could happen bad if rust allowed this issue to live.
We can try to get to the point from a different angle and to find logic errors in a wild, and then to speculate how type invariants might prevented them if programmers had written their types in a some particular way. But it raise a question: would they write their types in this way before they faced this particular logic error?
If I tried to talk about complex relationships of Rust and logic errors, I would need to dive into an ocean of speculations. Rust deniers are not very cooperative on this regard, and I'd bet they would just dismiss all the speculations as... well... speculations. And they would keep insist that if we cannot measure a falling frequency of logic bugs, then it is all immaterial. Some even go further and claim that if some tool doesn't prevent all bugs of a kind, then it is a useless thing.
So it is not a fun to talk about logic errors with rust deniers. Among rust evangelists the talk doesn't happen either, because they do not split bugs into two categories "logic" and "memory" bugs, they split them into "can be prevented by type invariant" and "cannot be prevented by type invariant, or too f*king difficult to". They talk about memory safety to laymen because it is something that laymen understand and it doesn't need explaining. And Rust can prevent all the bugs of this kind, so even when we talk to a people who thinks in black-and-white, we can make statements that are defensible in this Aristotelian tradition of excluded middle.
But Rust does do that, match exhaustiveness, forcing the handling of errors and the type system enables things like CreuSAT [1] using creusot [2]
[1] https://news.ycombinator.com/item?id=31780128
[2] https://github.com/xldenis/creusot
> Creusot works by translating Rust code to WhyML, the verification and specification language of Why3. Users can then leverage the full power of Why3 to (semi)-automatically discharge the verification conditions!
Units of Measure, https://github.com/iliekturtles/uom
The base properties of the language enable things that can never be done in C++.
Wow.
There are straw men and then there are straw man armies. This is probably the biggest one I've seen yet.
Hopefully in 20 years or less we will see unsafe code in the same way we view leaded gas, cigarettes and CO2. The other thing I realized in the last couple years is that eventually, everything becomes safety critical to someone at some point. That if you think you have to just protect this one system but that others can fail, is flawed on large scales. You can't tractably realize the failure graph, and nor can you prevent a seemingly innocuous thing from being used in a critical way.
The pandemic was a great lens into how human resilience kept flawed systems functioning in a way that few realized were flawed. The pharmacies in my area are still recovering only to have their problem exacerbated by more rigid controls that prevent local autonomy from making the system resilient. In this particular case, automation has made a problem worse by preventing humans from doing the little local silent repairs that they were previously doing.
1. Wearing a bicycle helmet is unpleasant, so people will cycle less and possibly use other modes of transportation such as cars. The risk of a traumatic head injury may decrease but this is offset either partially or fully by other health risks such as obesity.
2. Other road users in heavier vehicles (e.g. cars) perceive riders wearing bicycle helmets as less vulnerable, and so keep less distance when overtaking them, thus wearing a helmet increases the risk of collision.
I don't think I've ever heard someone say they won't wear a bicycle helmet because it would make them personally drive more dangerously.
I personally strongly oppose mandatory bike helmets. I think one of the reasons so many people own and ride bikes in my country (The Netherlands) is that we don't have mandatory helmets. Making helmets mandatory for people inside cars would also prevent or reduce head injuries (and indeed that is why they are worn by race car drivers) so if we ever introduce mandatory bicycle helmets here perhaps we can introduce mandatory car helmets at the same time, to ensure that people won't just take a car instead.
I don't think that's true. Sure, there are zealots who oversell things, but reasonable people (including those who are actual leaders in the Rust community) are realistic about the classes of bugs that Rust eliminates, as well as those Rust doesn't help with.
1. Rust does not protect you at compile time against "index out of bounds" errors. If you want that, you'll want a dependently-typed language like Idris. Which still wouldn't help much in this case.
2. However, Rust catches index errors perfectly well at runtime, and performs a controlled panic. This does not result in a privilege escalation, but it may cause a denial of service. So fuzzing in (safe) Rust is normally a "lower stakes" activity.
3. "cargo fuzz" is super easy to use, and AFL is pretty amazing.
4. If you think you can parse complex, badly-documented low-level binary formats without ever having an index error, you're probably wildly overconfident. In the case of the minidump parser, it's worse: The data was generated by a crashing process, and in many cases, the data caused the crash.
Let's look at what the author concludes:
> And what did we screw up? Some legit stuff! It’s Rust code, so I am fairly confident none of the issues were security concerns, but they were definitely quality of implementation issues, and could have been used to at very least denial-of-service the minidump processor.
A whole bunch of issues, probably none of them leading to security escalations. And unlike many C fuzzing experiences, it was largely painless:
> By comparison I am absolutely thriving under “Yeah you can deterministically trip this assertion with this tiny input you can just check in as a unit test”.
This happens because Rust catches most of these errors very early, using assertions in the standard library. So your fuzz reports often need to be tracked for only a few lines.
TL;Dr: Parsing complex binary formats usually involves subtle bugs. Rust does not promise to catch index-out-of-bounds at compile-time, but it catches them at runtime. This makes fuzzing easy and productive.
Overall, I'd call this a success story. The author underwent an inevitably humbling experience for low stakes under controlled conditions. And now the library can parse corrupted examples of an incredibly nasty format, with high confidence that the worst thing that will happen is a runtime error (not even a DoS).
This is a fun mistake. It’s “Palate cleanser”.