This is morally equivalent to invoking gdb against yourself. All bets are off. Cute! :)
Opening files should be considered unsafe.
This was actually half-seriously proposed, and the conclusion of the conversation was basically what’s described in the blog post: some things are outside of our capacity to reasonably model, and making something like opening files unsafe would be so unwieldy as to get in the way of people trying to use Rust productively.
Any formal model proves things only under the assumptions of the system, and usually one of those assumptions is “memory doesn’t just change from external forces.” If you violate that (this trick / cosmic rays or hardware failure flipping a bit / Rowhammer) then you can do things the model claims to prevent. However, these events are unlikely, so you still get strong, high-assurance conclusions from models like Rust’s various safety mechanisms.
Yes. I just opened an issue on the Monte reference interpreter to discuss it. Because Monte is a capability-aware language, we should expect the runtime to help us here.
In Monte, opening files is somewhat unsafe. Specifically, we only allow opening files through an “entrypoint capability”; these are special objects that are passed to the entrypoint where a program begins execution. The capability to open files is hopefully distinct from the capability to walk the current process’s heap, and currently they have two different names (makeFileResource and currentProcess).
A program might have been invoked with a copy of gdb attached to its stdout. A program might print “please attach gdb to this process and type in the following commands…” on a terminal. ;)
That was once very useful to get a backtrace on crash on an unusual system.
Starting gdb at process start and writing the relevant commands to its stdin in the SEGV handler worked a treat.
You jest but just wait a few more years and you’ll find this in commercial codebases around the world. Sooner or later someone will just need to do a damn typecast and be done with it, because clean code is important but we have to provide value for our customers first and foremost or something like that.
Did you read the code? Someone lazy would just use actual unsafe code. Or if worst comes worst they might manually muck with pointers to change an enum discriminant in a strange way. But opening their own process memory map as a file and fiddling with that directly? That’s just bananas.
Files aren’t unsafe in Rust. The author has no other reason for taking this approach. So I highly doubt opening /proc/self/mem will become common in commercial codebases, given how trivially you can execute this same approach within an unsafe block.
I get the cynicism about software quality, especially in commercial software. But I just think this one is a stretch.
Someone lazy would indeed just use actual unsafe code which is why Rustverity, when such a thing will exist, expensive consultants and all, is going to pop up a big red warning about unsafe code and eventually the people who write it will have uncomfortable meeting with their manager (or worse, their manager will have uncomfortable meetings with their manager about how our codebase is unsafe). So if you’re lazy, that will be a no-go. Importing the totally_safe_transmute crate and using it, on the other hand, won’t be a problem.
There’s an old saying that determined FORTRAN programmers can write FORTRAN in any language, but it holds true for a lot of languages, including C++ :-).
Of course this is mostly cynicism but hey, that way, I’m rarely disappointed!
Don’t worry, totally-safe-transmute crate will get permanently unfixed advisory in RustSec database and cargo-audit will pop up a big red warning. Rust people do care about these issues.
The author mentions this, but it seems very weird that the compiler works out that let E::U(v) = v will always fail and then just … compiles the dead code anyway.
let E::U(v) = v
Why does that seem weird to you? v is an immutable constant initialized to the enum variant of type E::T – by the normal rules of the language that if statement can never succeed, because v can’t have changed type after initialization.
It’s not really any different than writing let x = 3; if x == 4 .... Any compiler that isn’t miserably bad at optimization is going to skip that check. You want compilers to use their knowledge of compile time constants to avoid unnecessary work, after all.
let x = 3; if x == 4 ...
Edit: completely misread the comment, disregard me
You may have misread @nickzoic’s statement. They’re saying it’s weird the dead code wasn’t removed, but instead left in and then run after the discriminant-modifying trick in this code.
Whoops, yeah, thanks. I clearly need more coffee
This isn’t right.
This isn’t even wrong.
Tortoise vs Achilles’ record player♥