-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add debug asserts to some unsafe operations #51713
Comments
I think we would need at least three This gets out of hand quickly. Given
which makes it 2^6 = 64 different Honestly, we need something better. In my opinion, the options that a user specifies for its crate should apply to the whole dependency graph, including the |
I disagree that code that, for example, calls This absolutely makes sense for unreachable_unchecked since the invariant can be checked with no 'false positives' |
The idea is to explicitly construct slice which will cover valid memory region before indexing it, e.g. // method is unsafe because slice can contain uninitialized data
unsafe fn get_cap_slice(&self) -> &[T] {
slice::from_raw_parts(self.buf.ptr, self.buf.cap)
} Yes, this change will require more steps for some use-cases, but arguably it's worth it, as many consider |
Hi, I just want to say that I came across the same issue: and I was thinking, wouldn't it be possible to do something like that for #[macro_export]
macro_rules! unreachable_unchecked {
() => ({
#[cfg(debug_assertions)]
panic!("internal error: entered unreachable code")
#[cfg(not(debug_assertions))]
std::hint::unreachable_unchecked()
});
($msg:expr) => ({
unreachable_unchecked!("{}", $msg)
});
($msg:expr,) => ({
unreachable_unchecked!($msg)
});
($fmt:expr, $($arg:tt)*) => ({
#[cfg(debug_assertions)]
panic!(concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
#[cfg(not(debug_assertions))]
std::hint::unreachable_unchecked()
});
} As a macro, it would be expanded at crate compilation time and so would respect the (this code is inspired by the |
"crate compilation time" is the time that you're compiling std, not the downstream crate. |
It seems like the checks we already have already cause a very notable slowdown when building rustc with debug assertions enabled. We mitigated this a bit by making some checks abort instead of panic on failure (avoiding unwind paths), but this still still something to be aware of. It might be a good idea to have a separate |
@RalfJung |
It is quite common for compiler contributors to enable debug assertions in the compiler (this helps catch many bugs). This also enables debug assertions in libstd which makes the generated compiler a lot slower. With #72146 we now have the option of only enabling debug assertions in rustc and not libstd, but contributors still have to know to do that. And the more people do this, the less coverage we have for these debug assertions... |
I think we now have answers to the two main blockers. Just commenting here because I haven't seen these answers mentioned.
These assertions would still be useful for developers, because Cargo has Perhaps if there is any concern left here, it is that just adding
|
Maybe I deserve this for commenting so quickly after learning about this issue, but it seems that while |
Add debug assertions to some unsafe functions As suggested by rust-lang#51713 ~~Some similar code calls `abort()` instead of `panic!()` but aborting doesn't work in a `const fn`, and the intrinsic for doing dispatch based on whether execution is in a const is unstable.~~ This picked up some invalid uses of `get_unchecked` in the compiler, and fixes them. I can confirm that they do in fact pick up invalid uses of `get_unchecked` in the wild, though the user experience is less-than-awesome: ``` Running unittests (target/x86_64-unknown-linux-gnu/debug/deps/rle_decode_fast-04b7918da2001b50) running 6 tests error: test failed, to rerun pass '--lib' Caused by: process didn't exit successfully: `/home/ben/rle-decode-helper/target/x86_64-unknown-linux-gnu/debug/deps/rle_decode_fast-04b7918da2001b50` (signal: 4, SIGILL: illegal instruction) ``` ~~As best I can tell these changes produce a 6% regression in the runtime of `./x.py test` when `[rust] debug = true` is set.~~ Latest commit (rust-lang@6894d55) brings the additional overhead from this PR down to 0.5%, while also adding a few more assertions. I think this actually covers all the places in `core` that it is reasonable to check for safety requirements at runtime. Thoughts?
FWIW, with https://github.com/RalfJung/cargo-careful it becomes fairly easy for people to run their code with a stdlib that has debug assertions, so these assertions should be much easier to apply to real-world code now. :) |
So it looks like a lot of debug assertions were added in #92686. Looking through various cases, it appears that the following from the list above are covered by some form of debug assertion:
Some notable missing cases I found:
I've opened #105117 to address these. Also there are a lot of number-related unchecked operations that's aren't covered:
But I'm not sure if adding debug assertions for those would be welcomed. |
My not-libs opinion is that we should have some way to make all of these checked. Debug assertions might not be the best switch for these, but keeping them all behind And just in case this is what you're worried about: I do not think runtime overhead is a good argument against adding more of these. We started with things like |
Add more debug assertions to unsafe functions related to rust-lang#51713
I think this issue can be closed in favor of #120848? |
Yes, that list is much more up-to-date than the one here. |
The following functions have restrictions which (ideally) should be respected:
get_unchecked
get_unchecked_mut
slice_unchecked
slice_mut_unchecked
unreachable_unchecked
It would be nice to check these restrictions with debug asserts. The main blockers:
cargo
to switch between them depending on a compilation profile.src/liballoc/vec.rs
). Probably it should be rewritten in a more "correct" fashion.See internals thread for additional discussion.
The text was updated successfully, but these errors were encountered: