@@ -136,6 +136,27 @@ fn required_panic_strategy(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<PanicStrat
136
136
137
137
for def_id in tcx. hir ( ) . body_owners ( ) {
138
138
if tcx. has_ffi_unwind_calls ( def_id) {
139
+ // Given that this crate is compiled in `-C panic=unwind`, the `AbortUnwindingCalls`
140
+ // MIR pass will not be run on FFI-unwind call sites, therefore a foreign exception
141
+ // can enter Rust through these sites.
142
+ //
143
+ // On the other hand, crates compiled with `-C panic=abort` expects that all Rust
144
+ // functions cannot unwind (whether it's caused by Rust panic or foreign exception),
145
+ // and this expectation mismatch can cause unsoundness (#96926).
146
+ //
147
+ // To address this issue, we enforce that if FFI-unwind calls are used in a crate
148
+ // compiled with `panic=unwind`, then the final panic strategy must be `panic=unwind`.
149
+ // This will ensure that no crates will have wrong unwindability assumption.
150
+ //
151
+ // It should be noted that it is okay to link `panic=unwind` into a `panic=abort`
152
+ // program if it contains no FFI-unwind calls. In such case foreign exception can only
153
+ // enter Rust in a `panic=abort` crate, which will lead to an abort. There will also
154
+ // be no exceptions generated from Rust, so the assumption which `panic=abort` crates
155
+ // make, that no Rust function can unwind, indeed holds for crates compiled with
156
+ // `panic=unwind` as well. In such case this function returns `None`, indicating that
157
+ // the crate does not require a particular final panic strategy, and can be freely
158
+ // linked to crates with either strategy (we need such ability for libstd and its
159
+ // dependencies).
139
160
return Some ( PanicStrategy :: Unwind ) ;
140
161
}
141
162
}
0 commit comments