4 ms·
This is important for anyone considering using Rust. I was mistaken about the meaning of Rust's safety guarantees before reading this.
by gregwtmtno 11y ago
This is important for anyone considering using Rust. I was mistaken about the meaning of Rust's safety guarantees before reading this.
- Gankro 11y agoCare to elaborate as to what you thought they were?
- gregwtmtno 11y agoSure. First, thanks for the writeup. I had imagined that the Rust standard library used safe code all the way down. (Whatever that meant, I hadn't put all that much thought into it.) But as you state, "everything is built on top of unsafe." So I guess my understanding after reading this is that I could, using only "safe" code, accidentally manipulate the Rust standard library to cause undefined behavior, it's just much more unlikely in Rust than in C++.
- Gankro 11y agoOne important guarantee of Rust though: If you manage to do that, this is a bug in Rust and it's not your fault. And really, that's true of any "safe" language, right? Java, Ruby, Javascript, Python, whatever -- implementation errors mean your program will do crazy bad stuff, and we all have them.
- dschatz 11y agoJust to add to this point, the difference is that Rust can only guarantee this for the standard library. I can similarly write a library with safe interfaces that can be (ab)used to cause UB and there's little that the Rust team can do. This is different from other "safe" languages. This is why it's so important to establish what the responsibility and expectation is of library developers to uphold the safety guarantees that everyone else relies on. It only takes one bad library to destroy the safety guarantees everyone who is transitively using that library relies on.
- eslaught 11y agoThis is not all that different from Java (or Python, etc.), where it is quite easy to hide a call to a native function behind a seemingly-safe interface. The real difference is that native methods in Java must be written in a different language (C), while Rust supports both modes in the same language. (Edit: Or, if you prefer, two different but very closely related languages.) I would argue, at any rate, that this sort of safe/unsafe boundary is still useful for the purpose of auditing code. Conceptually, memory bugs are interactions between two points in the program: e.g. one location deallocates a pointer, then another tries to dereference it. With Rust's implementation of unsafe, you are guaranteed that any bad interactions must have at least one endpoint in an unsafe block. You still can't completely ignore the safe code, because unsafe code can reach arbitrarily far out of its box (so to speak), but in general this constraint does help significantly in limiting the amount of code that needs to be audited.
- rcxdude 11y agoIndeed. I have frequently segfaulted python by using certain modules (not even particularly obscure or low-quality ones either).
- Manishearth 11y agoAgreed. We had a segfault in Servo due to upgrading the compiler (and some internal representations changing). I wasn't able to track it myself (unfamiliarity with the code), but someone else was able to find its origin and fix it without much trouble because of `unsafe`. (That aside, we very rarely have segfaults in Servo, and Servo's huge)
- gregwtmtno 11y agoRight, but if you write a library using only Rust "safe" code, the guarantee is back on the Rust team. To me, it would be better if libraries using unsafe code were marked.
- sanderjd 11y agoHere's[0] an interesting idea for forcing crates using unsafe code to be handled specially, while allowing some "blessed" crates through without the special handling. [0]: https://github.com/rust-lang/cargo/issues/934#issuecomment-69425464 https://github.com/rust-lang/cargo/issues/934#issuecomment-6...