6 ms·
One thing I've realized with Rust is that its guarantees are a moving target. Today we can guarantee (barring compiler errors) memory safety in safe rust, but n
by staticassertion 6y ago
One thing I've realized with Rust is that its guarantees are a moving target. Today we can guarantee (barring compiler errors) memory safety in safe rust, but not unsafe rust.
But that story is improving. For one thing, we have people working to build safe abstractions for more unsafe use cases, at zero cost. We also have people improving fuzzing, and in theory safe rust code grows at a much faster rate than unsafe rust code, so fuzzing is far more tractable. We have people working on proving more about rust code, even when unsafe is around.
I'm quite excited to see how far Rust is able to go, I don't believe the state today is the end at all.
- Animats 6y agoToday we can guarantee (barring compiler errors) memory safety in safe rust, but not unsafe rust. Not quite. An unsafe function can export its lack of safety to other code. If an unsafe function can be called with parameters which make it violate memory safety, it opens a hole in memory safety.
- burntsushi 6y agoCalling an unsafe function can only be done inside an unsafe block.
- saagarjha 6y agoI’m unsure what you’re responding to. As I understood it, the comment took issue with saying that you can make guarantees about safe Rust but not unsafe Rust because unsafe Rust is not verified in that way and opens the door to violating guarantees in your “safe” code if your bugs leak out.
- PudgePacket 6y agoCan you rephrase or restate your point? It's really hard to understand..
- burntsushi 6y agoThat may be what you understood, but that's not what Animats said. See my reply above for more of an elaboration: https://news.ycombinator.com/item?id=24028359 https://news.ycombinator.com/item?id=24028359
- the_duke 6y agoI assume OP s point is that unsoundness or UB in an unsafe block is not contained in that block, but can taint safe code anywhere in the program. Which is true.
- XMPPwocky 6y agoonly if that block, or something in its "trusted set" (my term, for things in the same module that can access private members) is incorrect, though. safety/unsafety in Rust is factorable, which is a key part of the reason Rust is useful at all.
- vinay_ys 6y agoRest of your program blindly believes that the interface of your "trusted set" is safe because you owned that responsibility when you marked it unsafe. If you have a memory safety bug in that interface, then you can taint the rest of the program's memory safety as well, correct?
- PudgePacket 6y agoYes, that's the whole point though.
- ridiculous_fish 6y agoI think that is too strong. Consider this code: unsafe { libc::fork() }; let v = vec![1]; This may hang or even crash (malloc in the child) but there's no sense in which the unsafe block is "incorrect." Some unsafe code has unavoidable implications for the entire program.
- burntsushi 6y agoIndeed, some uses of unsafe aren't meaningfully factorable. File backed memory maps or shared memory with other processes are other important real world examples that are difficult or impossible to meaningfully factor in the context of a single process. But I still think that saying "safety in Rust is factorable" is accurate beyond a mere first approximation. Figuring out how to encapsulate unsafety is, in my experience, the essential creative aspect to using unsafe at all. Because if safety wasn't something you could encapsulate, then Rust really wouldn't be what it is. (I have spent many long hours thinking about how and to what extent the safety of file backed memory maps could be encapsulated. Which is to say, factoring safety is really the ultimate goal, even if certain things remain beyond that goal.)
- tsimionescu 6y agoBut you can expose unsafe code with a safe API, right? The point of the GP was that any safe code using this safe API could in fact be memory unsafe is there is a bug in the unsafe implementation.
- imtringued 6y agoYes but it's easy to take this too far and conclude that e.g. Javascript is not memory safe because browsers are written in C++ and they have to interface with the kernel which is written in C. At some point you simply need to trust that the current implementation is correct and bug free. This is also a problem with formal verification. What verifies the verification?
- burntsushi 6y agoYes, of course you can. But that's not what Animats said. Animats specifically said "unsafe function," which means you need to use the unsafe annotation to call it. See my other reply for more elaboration: https://news.ycombinator.com/item?id=24028359 https://news.ycombinator.com/item?id=24028359
- jfkebwjsbx 6y agoThey say can call though, so they are correct: if you can call then you are in an unsafe context.
- burntsushi 6y agoYes...? But they're responding to a point about safe Rust. See my other comment: https://news.ycombinator.com/item?id=24028359 https://news.ycombinator.com/item?id=24028359
- Animats 6y agoThe function containing the unsafe block can be called from safe code. So unsafe functionality can be exported. Said unsafe functionality might not be safe for all possible inputs. That's a classic hole, as with APIs that can be exploited.
- burntsushi 6y agoThen that's a "function containing an unsafe block," not an "unsafe function." In any case, this is still a misunderstanding of what staticassertion said. I elaborated more here: https://news.ycombinator.com/item?id=24028359 https://news.ycombinator.com/item?id=24028359 My bigger point here is that you're misunderstanding the advocated Rust value proposition. The value proposition isn't literally "Rust will forever and always eliminate all memory safety bugs in safe Rust." That's silly and no serious person with any credibility would double down on that claim.
- drran 6y agoYep. For example, it's easy to make intentional memory leak in Rust using safe API, which is unsafe. However, it's also easy to find such memory leak. Rust cannot stop you from doing weird things, when you want this, but it can help you to prevent, or quickly find, weird things, when you don't want them in your code.
- EE84M3i 6y ago"For example, it's easy to make intentional memory leak in Rust using safe API, which is unsafe." In what way is leaking memory in rust unsafe?
- drran 6y agoIt's a safe way to crash program by OOM killer. :-)
- Const-me 6y ago> However, it's also easy to find such memory leak. How? By manually inspecting all code in the project + dependencies marked with "unsafe"? The approach doesn't scale past "hello world" level of complexity. I don't code Rust, using C# for same purpose. I remember couple times I spend hours debugging weird crashes caused by stupid bugs in totally unrelated unsafe C# code. It's much easier to find memory leaks or native memory corruptions in C++, than in unsafe subset of a memory safe language. C++ has lots of runtime support for that (especially in debug builds), and many great tools, both in the compilers and external ones. Unsafe C# has none of them.
- steveklabnik 6y agoYou can also use those tools on Rust. It looks close enough that’s it’s fine. Valgrind, fuzzers, that stuff still works.
- Const-me 6y agoSimpler stuff like debug C heap, and checked iterators in C++ standard library, catch 95% of memory corruption issues in C++. These are enabled by default in debug builds, very often just pressing F5 in visual studio finds the buggy line of code in a matter of seconds. Valgrind is Linux-only, I don’t have it. One Windows equivalent is memory profiler under Debug / Performance Profiler / Memory Usage in visual studio, Rust is not supported by visual studio. A cross-platform equivalent is Intel VTune Profiler, no support for Rust either.
- dataking 6y agoWhile some patterns that call for unsafe today might be eliminated in whole or part, code that violates the ownership and borrowing rules will have to remain unsafe. I think fuzzing is not guaranteed to reach all unsafe code paths, nor provide full test coverage. Ideally, you want a) some sort of formal proof that the unsafe code cannot violate memory safety, b) 100% branch coverage for unsafe code, or c) both (because profilers and proofs can be wrong too :) edit: grammar.
- EE84M3i 6y agoWhy does code violating the rules have to stay unsafe? Haven't the rules been improved before? Why won't they be improved again?
- foota 6y agoWhat I really want is an integration of automated proof checking with unsafe code, allowing completely safe rust programs. Additionally, this could be extended to safe code to allow removing overhead from safety in things like bounds checks and Rc.
- zozbot234 6y agoThis requires a formal semantics for Unsafe Rust. It's a hard problem, albeit one that's being worked on.
- foota 6y agoI'm aware that however it's done it'll be hard. Does it really require formal semantics for unsafe rust though? I'm not familiar enough with rust to give an example, but if you imagine there's the unsafe rust level and beneath that the "machine code" (not actually machine code, just at the abstraction level equivalent to it) you should be able to hand write what the rust code is doing, without requiring the compiler to construct the machine level operations. With a formal semantics the proof checker just checks that the written proof (at rust level) matches with the rust code, but requires as you said an understanding of how unsafe rust interacts with the proof, whereas with a proof written at machine level, you don't need to understand the rust semantics, you just need to translate the rust to machine level and then check the proof there. Perhaps the machine level could be some layer in llvm? I'm only a little familiar with compilers, and hardly at all with more complicated compiler theory, but this seems reasonable to me.
- ridiculous_fish 6y agoLots of talk about formal methods, but I think the high order bit would be for unsafe code to use debug_assert! to check its preconditions. Right now it doesn't, because of rather silly technical reasons regarding how libcore is built and tested.