6 ms·
> Things having unsafe {...} does not make them unreliable. On the contrary, if you run into a memory issue in a rust program, you know where to look for it Th
by Capricorn2481 11mo ago
> Things having unsafe {...} does not make them unreliable. On the contrary, if you run into a memory issue in a rust program, you know where to look for it
This isn't true, no matter how much people keep saying it. Unsafe does not scope bugs to the block, or even where you have to look for bugs. Just having unsafe in your codebase means changing code outside the unsafe block could cause UB.
Doesn't mean I think it's worth complaining about, there's really no better way for Rust to do this without sandboxing memory.
- vacuity 11mo agoInternal use of unsafe requires securing the safe code at the module boundary. However, the design of unsafe still greatly reduces the burden of memory safety, both when it is and isn't used directly. The specific semantics of Rust aside, unsafe is more or less the ideal way for a language to express unsafe escape hatch constructs.
- Capricorn2481 11mo ago> Internal use of unsafe requires securing the safe code at the module boundary Not even that, because you can pass data structures from unsafe code at arbitrary depth.
- vacuity 11mo agoIf the goal is to make a safe abstraction, which is what I'm talking about, proper use of visibility and safe code at the module boundary encapsulates the unsafe code soundly. You seem to be talking either about improper encapsulation or unsafe that is intended to be exported and used unsafely. Or perhaps some method that is not sound according to the language.
- Dylan16807 11mo agoIf changing the safe code causes UB, the actual bug is in the unsafe code.
- tialaramex 11mo agoThis is very true from outside an encapsulation, but within the private implementation of a type there may be safe Rust that's required to uphold some assumptions made by the unsafe Rust [if there is some] and while in theory the bug is in the incorrect assumption made by the unsafe Rust in practice we're going to fix the "safe" code which broke our assumption instead.
- Capricorn2481 11mo agoNope. I would encourage you to actually read what unsafe does, because nowhere in the Rust docs does it say "scopes bugs to the unsafe block" See the below code. The unsafe code is doing exactly what it's supposed to. The safe code frees a value while it's being used. This compiles. There's nothing to change here in the unsafe code. ```rust use std::slice; // Unsafe block that creates a slice from raw parts fn make_slice(ptr: *const i32, len: usize) -> &'static [i32] { unsafe { slice::from_raw_parts(ptr, len) } } fn main() { let vec = vec![1, 2, 3, 4, 5]; let ptr = vec.as_ptr(); let len = vec.len(); // Unsafe block creates the slice - this operation itself is fine let slice_ref = make_slice(ptr, len); // Safe code: drop the vec drop(vec); // Safe code: use the slice - CRASH/UB println!("{:?}", slice_ref); } ```
- aw1621107 11mo agoI think one can argue make_slice is in fact at fault here since it's unsound (i.e., it doesn't enforce the requirements of from_raw_parts() and so allows safe code to invoke UB) and therefore either should be marked unsafe or should actually enforce the requirements of from_raw_parts(). That being said, I think in this context that's more of a nitpick since you're right in stating that bugs that result in UB need not be scoped strictly to unsafe blocks.
- Dylan16807 11mo agoThe unsafe code is not fulfilling the contract of "unsafe", which requires the coder to uphold the memory safety rules as seen from outside. make_slice is putting a very wrong lifetime on the slice it returns.
- imtringued 11mo agoThis is true. If you consider unsafe memory to be a separate region in Rust, your safe Rust code can still have pointers to unsafe memory. The only solution to this problem is to perform some sort of validation of the returned data structures every time they are returned by an unsafe block.