zlacker

[parent] [thread] 16 comments
1. jmilli+(OP)[view] [source] 2022-10-02 15:55:49
Rust doesn't have an official `#[never_panic]` annotation, but there's a variety of approaches folks use. Static analysis (Clippy) can get you pretty far. My favorite trick is to link a no_std binary with no panic handler, and see if it has a linker error. No linker error = no calls to panic handler = no panics.

Note that Rust is easier to work with than C here, because although the C-like API isn't shy about panicking where C would segfault, it also inherits enough of the OCaml/Haskell/ML idiom to have non-panic APIs for pretty much any major operation. Calling `saturating_add()` instead of `+` is verbose, but it's feasible in a way that C just isn't unless you go full MISRA.

replies(2): >>ajross+vc >>pdimit+xn
2. ajross+vc[view] [source] 2022-10-02 17:01:28
>>jmilli+(OP)
> Static analysis (Clippy) can get you pretty far.

What's funny about this is that (while it's true!) it's exactly the argument that Rustaceans tend to reject out of hand when the subject is hardening C code with analysis tools (or instrumentation gadgets like ASAN/MSAN/fuzzing, which get a lot of the same bile).

In fact when used well, my feeling is that extra-language tooling has largely eliminated the practical safety/correctness advantages of a statically-checked language like rust, or frankly even managed runtimes like .NET or Go. C code today lives in a very different world than it did even a decade ago.

replies(6): >>jmilli+Ke >>lifthr+rf >>j-krie+Ri >>tialar+Ro >>P5fRxh+C01 >>pjmlp+iW3
◧◩
3. jmilli+Ke[view] [source] [discussion] 2022-10-02 17:13:37
>>ajross+vc
Analysis for memory safety is really hard. For >40 years there's been entire sub-industries focused just on analysis of C/C++ memory safety and it's nowhere near a solved problem. That's why Rust has `unsafe`, it's so the programmer has a way to encode logic that they believe is safe but aren't yet able to prove.

Analysis of panic-safety in Rust is comparatively easy. The set of standard library calls that can panic is finite, so if your tool just walks every call graph you can figure out whether panic is disproven or not.

replies(1): >>ajross+7g1
◧◩
4. lifthr+rf[view] [source] [discussion] 2022-10-02 17:18:13
>>ajross+vc
While C/C++ has been made much safer by sanitizers, fuzzing and lints, they are:

- Only useful when actually being used, which is never the case. (Seriously, can we make at least ASAN the default?)

- Often costly to always turn them on (e.g. MSAN).

- Often requires restructuring or redesign to get the most out of them (especially fuzzing).

Rust's memory safety guarantee does not suffer from first two points, and the third point is largely amortized into the language learning cost.

replies(1): >>pjmlp+TW3
◧◩
5. j-krie+Ri[view] [source] [discussion] 2022-10-02 17:35:29
>>ajross+vc
The difference being that C is barely changed for the sake of backwards compatibility while the panicking in kernel space is a recognized problem with rust that is being actively worked on and will have a solution in the future.
6. pdimit+xn[view] [source] 2022-10-02 18:00:47
>>jmilli+(OP)
> My favorite trick is to link a no_std binary with no panic handler, and see if it has a linker error. No linker error = no calls to panic handler = no panics.

Oh? How do you do that? Do you have a written guide handy? Very curious about this.

◧◩
7. tialar+Ro[view] [source] [discussion] 2022-10-02 18:07:46
>>ajross+vc
Rust makes choices which drastically simplify the analysis problem.

The most obvious is mutable references. In Rust there can be either one mutable reference to an object or there may be any number of immutable references. So if we're thinking about this value here, V, and we're got an immutable reference &V so that we can examine V well... it's not changing, there are no mutable references to it by definition. The Rust language won't let us have &mut V the mutable reference at the same time &V exists and so it needn't ever account for that possibility†.

In C and C++ they break this rule all the time. It's really convenient, and it's not forbidden in C or C++ so why not. Well, now the analysis you wanted to do is incredibly difficult, so good luck with that.

† This also has drastic implications for an optimiser. Rust's optimiser can often trivially conclude that a= f(b); can't change b where a C or C++ optimiser is obliged to admit that actually it's not sure, we need to emit slower code in case b is just an alias for a.

replies(1): >>ajross+sm1
◧◩
8. P5fRxh+C01[view] [source] [discussion] 2022-10-02 22:19:40
>>ajross+vc
I've long been of the opinion that the rust community is missing the boat in a lot of respects.

Rust could do the external tooling better than any other language out there, but they're so focused on the _language_ preventing abuse that they've largely missed the boat.

◧◩◪
9. ajross+7g1[view] [source] [discussion] 2022-10-03 00:18:58
>>jmilli+Ke
> That's why Rust has `unsafe`, it's so the programmer has a way to encode logic that they believe is safe but aren't yet able to prove.

That's not the right way to characterize this. Rust has unsafe for code that is correct but that the compiler is unable to detect. Foreign memory access (or hardware MMIO) and cyclic data structures are the big ones, and those are well-specified, provable, verifiable regimes. They just don't fit within the borrow checker's world view.

Which is something I think a lot of Rust folks tend to gloss over: even at it's best, most maximalist interpretation, Rust can only verify "correctness" along axes it understands, and those aren't really that big a part of the problem area in practice.

replies(1): >>kaba0+MF2
◧◩◪
10. ajross+sm1[view] [source] [discussion] 2022-10-03 01:14:24
>>tialar+Ro
That point would be stronger if Rust were showing up as faster than C compilers on this axis, and it isn't. In point of fact aliasing rules (which is what C calls the problem you're talking about) are very well travelled ground and the benefits and risks of -fno-strict-aliasing are well understood. Static analysis tools are in fact extremely good at this particular area of the problem. And of course at the level of emerging technologies, LTO makes this largely a non-issue because the compiler is able to see the aliasing opportunities at the level of global analysis. It doesn't need the programmer or the compiler to promise it an access is unaliased, it can just check and see.
replies(1): >>kaba0+cG2
◧◩◪◨
11. kaba0+MF2[view] [source] [discussion] 2022-10-03 13:37:14
>>ajross+7g1
I don’t really get your comment - are you agreeing or disagreeing with parent? Because you seemingly say the same thing.

And continuing on parent’s comment, rust can only make its memory guarantees by restricting the set of programmable programs, while C and the like’s static analysis has to work on the whole set which is simply an undecidable problem. As soon as unsafe is in the picture, it becomes undecidable as well in Rust, in general.

replies(1): >>ajross+Jl3
◧◩◪◨
12. kaba0+cG2[view] [source] [discussion] 2022-10-03 13:39:06
>>ajross+sm1
It’s not a problem, because compilers simply declare it as UB and don’t care about it. If you by accident did depend on that, your program will just get a nice, hard to debug bug.
◧◩◪◨⬒
13. ajross+Jl3[view] [source] [discussion] 2022-10-03 16:38:03
>>kaba0+MF2
The parent comment seemed to imply that using unsafe was a failing of the developer to prove to the compiler that the code is correct. And that's not right, unless you view thing like "doubly linked list" as incorrect code. Unsafe is for correct code that the compiler is unable to verify.
◧◩
14. pjmlp+iW3[view] [source] [discussion] 2022-10-03 19:06:04
>>ajross+vc
Static analysis for C exists since 1979, date of lint's availability, the problem isn't lack of tooling, rather people actually using it.
replies(1): >>jstimp+JC7
◧◩◪
15. pjmlp+TW3[view] [source] [discussion] 2022-10-03 19:08:42
>>lifthr+rf
> Seriously, can we make at least ASAN the default?

Android helps a bit into that sense,

https://source.android.com/docs/security/test/hwasan

◧◩◪
16. jstimp+JC7[view] [source] [discussion] 2022-10-04 20:29:45
>>pjmlp+iW3
I would assume that the things that lint could do you nowadays get by simply using -Wall -Wextra with gcc for example. While I haven't checked what a lint is required to do, but there have been plenty of situations in the past where I had to change my code in order to avoid triggering false positives from tests that run during normal compilation. For instance, there are tests that find accesses to potentially uninitialized variables.
replies(1): >>pjmlp+lu9
◧◩◪◨
17. pjmlp+lu9[view] [source] [discussion] 2022-10-05 10:21:36
>>jstimp+JC7
If we are talking about the 1979 version, most likely.

If we are talking about products like PC-lint, Sonar qube, Coverity, the experience is much more than that.

[go to top]