10 ms·
uh. No. Rust unsafe gives rust behavior a lot like C. If you at all break the rather subtle rules, then essentially anything can and will happen. So for exampl
by nullc 3y ago
uh. No. Rust unsafe gives rust behavior a lot like C. If you at all break the rather subtle rules, then essentially anything can and will happen.
So for example, there was recently a thread where someone had code that checked if a value was in range to safely coerce it directly to an enum then did so. But because of eager evaluation of an argument the unsafe cast happened first. From this the compiler reasoned that the variable was preconditionally range constrained to always be in range and it optimized out the in-range test (which itself was not unsafe code).
This is a classic C bug where someone implements an overflow check that itself can overflow, causing the branch for overflow to get optimized out. But at least in C the simpler syntax at least made it clear that the triggering code got executed first. The more complex rust syntax obscured that.
Rust has improved the situation by narrowing the cases where you can get into this trouble, but on the other hand it adds a lot of other complexity that contributes to faulty code (and a nearly mandatory packaging ecosystem which is a security nightmare-- it's the norm for even simple rust utilities to pull in a million lines of unauditable (just by bulk) third party code, including multiple HTTPS libraries).
As a result, I don't think it can be taken for granted that rust as a whole is an advancement in software integrity-- it may be, but it's something that ought to be formally studied. In some cases rust might be replacing memory safety bugs with an even greater number of other defects which, depending on the application, may be worse. (not everything is an internet exposed service where hacks are the only failure of consequence and where input really should be assumed to be intelligently adversarial.)
In any case, "break the rules and all bets are off" is an issue that likely will continue to exist in any performant language. Automatic code generation will generate stuff with awful performance unless an optimizer goes through and eliminates 'impossible cases', but optimization isn't possible unless the compiler can assume the rules are followed.
- Ar-Curunir 3y ago> As a result, I don't think it can be taken for granted that rust as a whole is an advancement in software integrity-- it may be, but it's something that ought to be formally studied. In some cases rust might be replacing memory safety bugs with an even greater number of other defects which, depending on the application, may be worse. I’m sorry, but without any supporting evidence for this claim, this is just FUD. Everything that we’ve seen in case studies of people reimplementing stuff in Rust indicates that memory safety and logic bugs are derived compared to something like C.
- nullc 3y agoCitation welcome to those case studies, because I've not seen them. It's on the advocates of rust to establish that it makes things better because it absolutely isn't unambiguous. We really seem to be in the stone age in terms of what practices lead to higher quality software. We still have people who chant "goto harmful" against one simply forward jumps to on-error-cleanup code, yet still litter their C++ and java with exceptions which are a less safe and less clear version of the same thing. I've personally found the rate of embarrassing errors in simple rust software is increased over comparable C code, but I freely admit that this experience is far from a formal study and may well be due to the lack of problem-domain competence or general haste in people participating in culty "re-implement in rust" exercises (and where the rust code is far more often someone's "learn rust" project). And at least where security w/ untrusted input is a concern the nature of the rust bugs is preferable to the bugs in comparable C code, but as mentioned that doesn't apply to a lot of software. Another data-point is that the vast majority of firefox crashes I experience now are rust panics, even though the amount of rust code is small compared to C++ code. It's hard to reason from that however, since it can be said that the rust code is more complex and more heavily used than the bulk of the rest.
- klabb3 3y agoI appreciate your comments in this thread. They are a healthy skeptical technology-neutral take unaffected by novel-paradigm-dogma – in this case about Rust, but it really applies to any software practice. I have nothing against Rust and I believe it has advanced the space of mainstream imperative languages significantly, particular in high performance low-level coding. But you have to always keep an eye on the horizon. > We really seem to be in the stone age in terms of what practices lead to higher quality software. I agree. What I always come back to is simplicity, or reducing total cognitive complexity. The only way I know of that actually consistently works, is modularization (in the most liberal sense of the word), in order for our human brains to work in a reduced problem domain at any given point in time. So whatever languages, protocols, tooling and design patterns help with that, I lean into, although this is (currently) a subjective measure. On some problems, it’s clear Rust is amazing in this respect, taking away certain worries so that you can focus on “what matters”. But this is not a truism in all domains, because the issues that Rust addresses are merely a good list, not an exhaustive one.
- Ygg2 3y ago> If you at all break the rather subtle rules, then essentially anything can and will happen. If by subtle rules you mean your invariants, that is missing fundamental assumptions. It's akin to making a building without foundation and load bearing structures. > So for example, there was recently a thread where someone had code that checked if a value was in range to safely coerce it directly to an enum then did so. But because of eager evaluation of an argument the unsafe cast happened first You mean this: https://notgull.net/cautionary-unsafe-tale/ https://notgull.net/cautionary-unsafe-tale/ However note the UB goes away if you never use any unsafe code. Or if you expand your unsafe to encompas some safe code. Issue it had was safe code was invalidating the invariants unsafe code was relying on. Iirc alignment.
- lmm 3y ago> If by subtle rules you mean your invariants, that is missing fundamental assumptions. > It's akin to making a building without foundation and load bearing structures. That's exactly how C approaches UB too. > However note the UB goes away if you never use any unsafe code. Or if you expand your unsafe to encompas some safe code. Right. The problem is that's untenable; any nontrivial program will have unsafe somewhere, and unsafe can cause failures arbitrarily far away from the incorrect code. The whole point of the article is that you need to be able to draw an actual boundary between the unsafe parts and the safe parts of your program and review the unsafe parts in isolation. If Rust doesn't give you more and better support in doing that than C does, then it's not really making a difference.
- nullc 3y agoExactly. All-hope-lost behavior is possible in rust code unless there is no unsafe anywhere (and no compiler bugs, but I think its fair to ignore those when discussing the language in the abstract). Rust potentially benefits from fewer opportunities to footgun yourself, but rust also comes with other costs (including a more complex syntax, a bad dependency culture, a lot more front-loaded cognitive load around lifetime management, etc.) which might offset those benefits. Some of those extra complexity costs seem hard (or impossible) to avoid when trying to keep memory safety from having a disproportional runtime cost, so I'm not necessarily faulting rust. But some of the sources of defects in rust code may also be entirely avoidable, which is why I think it's important to actually study it rather than axiomatically assume its behavior makes programs correct. It doesn't, even absent unsafe.