I thought the whole point of safe code was that any bugs in safe code cannot cause unsound behaivor, so it's on the unsafe code to maintain soundness even if it's used incorrectly by safe code?
I thought the whole point of safe code was that any bugs in safe code cannot cause unsound behaivor, so it's on the unsafe code to maintain soundness even if it's used incorrectly by safe code?
For example, in WGPU I get the surface of an OS window. This requires an unsafe function call. The invariant I must uphold is to not drop the window before the surface. This requires writing my safe code a certain way. And indeed, a malicious actor could change only safe code and cause UB by dropping the window (I believe this would cause a double free when the surface is dropped). However, the struct holding the window and surface presents a safe API to users of the struct, and no code outside the struct can cause UB.
Famous example is:
impl Vec {
pub unsafe fn set_capacity(&mut self, capacity: usize) {
self.capacity = capacity; // why is that unsafe?
}
}
What OP possibly did was invalidate his invariants in safe code.Of course, if there's one bug in unsafe code, then all bets are off, but that's still a bug in the unsafe code.
In code I'd consider high-quality, there'd be a comment like this [1]:
// SAFETY: inner is only mutated by foo, bar, and baz, all of which
// ensure the pointer is valid.
[0]: https://doc.rust-lang.org/std/primitive.pointer.html#method....[1]: https://std-dev-guide.rust-lang.org/policy/safety-comments.h...