Hacker News new | past | comments | ask | show | jobs | submit login

The branding (or at least the zeitgeist) around Rust is that it is a "safe language", which implies that bugs are all logic bugs or somehow the fault of the programmer for doing something "unsafe" (hence the keyword).

Anyone who thinks about it for a bit knows there are limits to guarantees of safety. It's notoriously impossible to prove that a program terminates appropriately, for instance.

So I can understand some shock to run into the arcane all of a sudden. It must be especially shocking because it feels especially out of place.




Rust is a safe language for a specific definition of safe regarding a class of memory errors.


Regarding multiple classes of memory errors I think. Many languages are memory safe from control flow takeover, rust extends this to data races corrupting data.


Rust (without `unsafe`) protects you from Undefined Behavior. Behavior that is defined as crashing your program doesn't fall under that.


I have chosen this as a hill to die upon:

Philosophically, the Halting Problem and the Pigeonhole Principle are very similar. They both talk about what is not possible with arbitrary input, but they have very little to say about practical input. You can't compress a random number generator. You can compress human communication, in any form, some of them famously. The existence of PP or HP are only boundary conditions, as entropy goes to infinity.

Humans also call entropy 'chaos', which has a connotation that's doubly meaningful in information theory. Chaos obfuscates. It's only useful when obfuscation is the point (encryption). We run away from it as fast as we can, and the farther we get from in the more interesting opportunities open up. Languages that disallow certain patterns can solve the halting problem for pieces of the application, maybe even entire 'useful' applications.


For some categories of applications, or even components of applications, the inability to meet a deadline in handling an event is a safety violation in the category of "or else people could die". I mentioned the halting problem instead since it's close enough to those requirements for an HN comment.

Rust has nothing special to say about that definition of safety, except that it thinks it has a better model for avoiding certain kinds of memory bugs that could contribute to those issues. Given that, I can see that "safe language" as a concept can be confusing and even leave engineers a little unprepared for unexpected categories of bugs.

Anyway, I brought up the halting problem to illustrate. I'm sure there are other illustrations you can substitute regardless of your opinion on the halting problem.


Rust is pretty clear about “safe” meaning no memory unsafety in unsafe-free code. It certainly doesn't market that code without unsafe will be bug free (this would force the safe subset to no longer be Turing complete).


It can still be surprising because in other languages it may be the case that a stack overflow can lead to memory unsafety. However, in Rust, a stack overflow leads to a guaranteed abort on major platforms, and a best-effort abort on niche platforms (the reason being that LLVM only provides stack probes for major platforms, so niche platforms have to make do with only guard pages).


My understanding is that there is a decent amount of undefined behavior on stack overflow in Rust, due to its use of TLS.

https://github.com/rust-lang/rust/issues/43146


I'm unclear how that would lead to undefined behavior on stack overflow. Stack overflow on Rust is specified to immediately abort the entire process (with some aforementioned wrinkles as to how achievable that is on certain targets), which necessarily nukes all TLS.

The fact that the linked issue isn't tagged with "I-unsound" suggests that nobody has ever indicated that that might somehow be a soundness issue. If you think otherwise, I encourage you to bring it up so that any soundness issue can be properly tracked.


To push this point a little further: in Rust when there's not a clean way to prevent memory unsafety (or when you haven't requested to), it aborts the process. Out of array indexing, stack overflows, etc.


Minor clarification: there's a difference between a "panic" (which may either unwind or abort, based on compilation flags) and a "guaranteed abort" (which is not negotiable). Array-index-out-of-bounds is merely a panic, as are almost all "unrecoverable errors" in Rust. Things that are guaranteed to abort are rare in Rust; I can only think of stack overflows, and OOM for certain stdlib types.


Various refcount overflows also abort: mpmc, Arc, Rc: https://doc.rust-lang.org/src/alloc/rc.rs.html#2628

I think we're lucky the usual "aha rust isn't so safe after all, checkmate rustaceans!" crowd hasn't run into these aborts yet, because they won't have any kind of debugging spew so are not very friendly. You have to intentionally leak refcounts to hit these aborts or else you first run out of memory just storing the pointers; but then again, intentionally leaking things is just the sort of thing the anti-rust crowd is likely to try.


Mostly once they discover they can leak things, Rust is pronounced "not really safe" by such people anyway.


My understanding is that the code which aborts the process contains the potential for UB.


As far as I know, in the case of stack overflow, the code that aborts the process should literally just be a single line of assembly that contains an invalid opcode, resulting in a (safe) segfault. What has given you the impression that there is potential for UB in these code paths?

EDIT: ah, I see your other comment.


Stack overflow in Rust does abort the process, but not immediately: the signal handler first distinguishes stack overflow from other sources of SIGSEGV/SIGBUS, and then prints a message containing the name of the current thread. Both of these require accessing TLS, which in turn may panic, or invoke other non-async-signal safe functions. That is UB.

I don't know what the definition of a "soundness issue" is, but I think there are some nasal demons to be found here; it will be fun to try at least.

edit the linked issue missed a case! Rust aborts by using libc::abort(), which is not async signal-safe in glibc prior to 2.26.


I have put a bug report where my mouth is. https://github.com/rust-lang/rust/issues/111272


Thanks for the report! We can continue there. :)


My point is more that debugging a core dump (and similar activities) would be all the more foreign. The engineer might even be shocked that the need to do that sort of thing even exists for a piece of Rust code.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: