-
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
Footgun with catch_unwind
when catching panic-on-drop types
#86027
Comments
#85927 adds |
cc @rust-lang/libs @rust-lang/compiler |
One option might be to somehow intervene (via an intrinsic or whatever) in the destructor of the Any trait object such that the destructor decrements the panic counter after running (i.e., the caught panic is still "panicking" until it's destructor runs). That would make any panics in that destructor cause an abort. It's not clear to me that this behavior is what's desired in all cases, but I'm not sure how much flexibility we have... it seems unlikely that someone actually wants alternative behavior and can't get it with downcasting or similar... |
Unfortunately I don't know how possible that will be to do in this particular situation, as (edit: I suppose it might be possible to use a flag in the low bits of the vtable pointer to indicate that |
We could deprecate |
Can we just change the return type to be |
You can use |
I personally feel that the long-term solution to this and other issues related to panic-on-dropis is to do what C++ did in C++11: destructors were changed to be |
A potentially less-invasive version of @Amanieu's proposal would be to only require trait object destructors to abort if they panic, and continue to allow panicking from other |
Why is this categorized Those unsoundness instances should be tracked and fixed separately, and this issue, I think, should remain as a plain footgun issue, rather than an I-unsound one. (As to why: I-unsound issues are usually prioritized differently, interpreted by passersby differently, and tend to be subject to various time consuming processes. I think given these things this nitpick is quite important ^^) Not allowing the destructors to panic would be great to simplify codegen significantly too, and would mostly remove another class of footguns (panic-while-panicking). That said, knowing how abundant destructors that run fallible code are, it would likely be quite difficult to justify this kind of change? |
If we make the
|
There are additional reasons why we may want to add an
|
@rustbot modify labels +T-lang -I-nominated We discussed this topic in today's @rust-lang/libs meeting. There is some traction behind #86027 (comment) (aborting on any unwind from a Drop impl) but that would be for the lang team to decide. @joshtriplett will follow up with the lang team -- rust-lang/lang-team#97. I promised to write up a counterproposal for how to proceed without any language change necessary. The approach I'd like is that The
with an example instance:
The implementation I'd like looks like:
This is a circular linked list of vtables. During the initial unsize coercion from Pseudocode: // https://doc.rust-lang.org/std/panic/fn.resume_unwind.html
pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
payload.vtable = payload.vtable.nonpanicking_drop_vtable;
/* now resume using `payload` as the Box<dyn Any>... */
} |
@dtolnay That seems very magical, and while equality on vtables is already broken, this would mean that there could never be a 1:1 correspondence between (trait/type pair) and (vtable pointer). Also, the way that this "abort on panic" property sticks around indefinitely on the value, even outside of the IMO, the best option is just to change existing code to fix the problem (without excluding #86027 (comment) as a future possibility). To assist with that change, we should introduce a new |
FWIW, I have submitted #99032 which offers one way to fix or at least palliate this |
(Replying here since it's not what the PR does.)
I would be rather opposed to that. I think we want to specify vtables in a way that it becomes entirely impossible for Rust code to actually generate a valid vtable -- any attempt of doing so will yield UB. vtables are "magic" and recognized by the Abstract Machine and that magic can not be replicated just by putting the same bits into some other memory. I plan to implement this in Miri in the near future. Under that version of Miri, that alternative implementation quoted above would be diagnosed as UB, notwithstanding the fact that it is in the stdlib. The stdlib is "privileged" to exploit implementation-specific behavior, but it cannot do anything about undefined behavior. |
btw this may be a hot take but has anyone tried documenting the current behavior with catch_unwind payload dropping? because it's currently not https://doc.rust-lang.org/stable/std/panic/fn.catch_unwind.html |
Maybe we should deny unwinding panic from drop in edition 2024? I. e. such drop should always abort, similarly to C++ default behavior? |
While #99032, which would conclusively solve this, issue has been sitting inactive for years, we should definitely add a note of this behavior to our docs. Fixing this properly is hard, but almost 3 years after learning about the problem we should definitely begin telling our users about it. (We should have done that long ago, but alas.) |
catch_panic: warn about panicking payload drop Warns about the footgun in rust-lang#86027. Will be unnecessary if panics escaping from drop leads to abort (rust-lang/rfcs#3288). But until that is enforced everywhere, let's warn users about this.
catch_panic: warn about panicking payload drop Warns about the footgun in rust-lang/rust#86027. Will be unnecessary if panics escaping from drop leads to abort (rust-lang/rfcs#3288). But until that is enforced everywhere, let's warn users about this.
catch_panic: warn about panicking payload drop Warns about the footgun in rust-lang/rust#86027. Will be unnecessary if panics escaping from drop leads to abort (rust-lang/rfcs#3288). But until that is enforced everywhere, let's warn users about this.
catch_panic: warn about panicking payload drop Warns about the footgun in rust-lang/rust#86027. Will be unnecessary if panics escaping from drop leads to abort (rust-lang/rfcs#3288). But until that is enforced everywhere, let's warn users about this.
Originally reported by @SabrinaJewson in #85927
catch_unwind(code)
is often used to make sure no panics fromcode
can cause further unwinding/panics. However, when catching a panic with a payload that panics on Drop, most usages ofcatch_unwind(code)
will still result in further unwinding and often unsoundness.Example in rustc (found by @mystor):
rust/compiler/rustc_ast/src/mut_visit.rs
Lines 299 to 300 in 5ea1923
Here, the
Result
containing the panic payload is dropped beforeabort()
is called, which might cause a panic.Edit: Looks like the
_
doesn't cause an immediate drop as a parameter, so this case works fine, possibly by accident.Another example in the standard library:
rust/library/std/src/rt.rs
Lines 34 to 39 in 5ea1923
And another case in the
proc_macro
bridge:rust/library/proc_macro/src/bridge/server.rs
Lines 115 to 116 in 5ea1923
The text was updated successfully, but these errors were encountered: