zlacker

[return to "“Rust is safe” is not some kind of absolute guarantee of code safety"]
1. jmilli+Fb[view] [source] 2022-10-02 15:34:06
>>rvz+(OP)
As usual HN comments react to the headline, without reading the content.

A lot of modern userspace code, including Rust code in the standard library, thinks that invariant failures (AKA "programmer errors") should cause some sort of assertion failure or crash (Rust or Go `panic`, C/C++ `assert`, etc). In the kernel, claims Linus, failing loudly is worse than trying to keep going because failing would also kill the failure reporting mechanisms.

He advocates for a sort of soft-failure, where the code tells you you're entering unknown territory and then goes ahead and does whatever. Maybe it crashes later, maybe it returns the wrong answer, who knows, the only thing it won't do is halt the kernel at the point the error was detected.

Think of the following Rust API for an array, which needs to be able to handle the case of a user reading an index outside its bounds:

  struct Array<T> { ... }
  impl<T> Array<T> {
    fn len(&self) -> usize;

    // if idx >= len, panic
    fn get_or_panic(&self, idx: usize) -> T;

    // if idx >= len, return None
    fn get_or_none(&self, idx: usize) -> Option<T>;

    // if idx >= len, print a stack trace and return
    // who knows what
    unsafe fn get_or_undefined(&self, idx: usize) -> T;
  }
The first two are safe by the Rust definition, because they can't cause memory-unsafe behavior. The second two are safe by the Linus/Linux definition, because they won't cause a kernel panic. If you have to choose between #1 and #3, Linus is putting his foot down and saying that the kernel's answer is #3.
◧◩
2. layer8+0d[view] [source] 2022-10-02 15:41:34
>>jmilli+Fb
Please correct me if I’m wrong, but Rust also has no built-in mechanism to statically determine “this code won’t ever panic”, and thus with regards to Linux kernel requirements isn’t safer in that aspect than C. To the contrary, Rust is arguably less safe in that aspect than C, due to the general Rust practice of panicking upon unexpected conditions.
◧◩◪
3. dcsomm+0g[view] [source] 2022-10-02 15:59:00
>>layer8+0d
> ... the general Rust practice of panicking upon unexpected conditions

What makes you say this? From the sample I've seen, Rust programs are far more diligent about handling errors (not panicking: either returning error or handling it explicitly) than C or Go programs due to the nature of wrapped types like Option<T> and Result<T, E>. You can't escape handling the error, and panicking potential is very easy to see and lint against with clippy in the code.

◧◩◪◨
4. layer8+Ng[view] [source] 2022-10-02 16:03:15
>>dcsomm+0g
I’m referring to the fact that ubiquitous functions like unwrap() panic if the programmer has made an error. Guarding against such panics is outside of the scope of Rust-the-language, and has to be handled through external means. There are linters for C as well.
◧◩◪◨⬒
5. Velila+cj[view] [source] 2022-10-02 16:15:56
>>layer8+Ng
I think I prefer Rust's way of doing things. Just last night I used the Vec! macro incorrectly putting in a comma instead of a semi-colon and despite the program compiling correctly, it immediately panicked with an OOB error. With C it would have been a lot harder to even notice a bug little alone track it down.
◧◩◪◨⬒⬓
6. layer8+uk[view] [source] 2022-10-02 16:23:09
>>Velila+cj
Right. My personal opinion is that exceptions provide a better trade-off between catching bugs and still allowing the chance of graceful shutdown or recovery.
◧◩◪◨⬒⬓⬔
7. Velila+Wm[view] [source] 2022-10-02 16:33:37
>>layer8+uk
In my case it wouldn't have raised an exception though, it would have just been UB.

It's not like there's not exceptions in Rust though. The error handling is thorough to a fault when it's used. Unwrap is just a shortcut to say "I know there might be bad input, I don't want to handle it right now, just let me do it and I'll accept the panic."

◧◩◪◨⬒⬓⬔⧯
8. layer8+fp[view] [source] 2022-10-02 16:45:39
>>Velila+Wm
By exceptions, I’m referring to languages with exceptions as a dedicated language construct with automatic stack unwinding, and preferably without UB (e.g. Java or C#). Rust doesn’t have exceptions in that sense.
◧◩◪◨⬒⬓⬔⧯▣
9. dureui+zC[view] [source] 2022-10-02 17:58:15
>>layer8+fp
But panics in rust are pretty much exceptions though?

The differences are they are actually meant to be used for exceptional situations ("assert violated => there's a bug in this program" or "out of memory, catastrophic runtime situation") and they are not typed (rather, the panic holds a type erased payload).

Other than that, it performs unwinding without UB, and is catchable[0]. I'm not seeing the technical difference?

[0]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html

◧◩◪◨⬒⬓⬔⧯▣▦
10. layer8+2F[view] [source] 2022-10-02 18:13:46
>>dureui+zC
You’re probably right now that I’ve read up on it, I wasn’t previously aware of catch_unwind.
[go to top]