Skip to content

Commit 4b4f53f

Browse files
committed
Auto merge of rust-lang#92911 - nbdd0121:unwind, r=Amanieu
Guard against unwinding in cleanup code Currently the only safe guard we have against double unwind is the panic count (which is local to Rust). When double unwinds indeed happen (e.g. C++ exception + Rust panic, or two C++ exceptions), then the second unwind actually goes through and the first unwind is leaked. This can cause UB. cc rust-lang/project-ffi-unwind#6 E.g. given the following C++ code: ```c++ extern "C" void foo() { throw "A"; } extern "C" void execute(void (*fn)()) { try { fn(); } catch(...) { } } ``` This program is well-defined to terminate: ```c++ struct dtor { ~dtor() noexcept(false) { foo(); } }; void a() { dtor a; dtor b; } int main() { execute(a); return 0; } ``` But this Rust code doesn't catch the double unwind: ```rust extern "C-unwind" { fn foo(); fn execute(f: unsafe extern "C-unwind" fn()); } struct Dtor; impl Drop for Dtor { fn drop(&mut self) { unsafe { foo(); } } } extern "C-unwind" fn a() { let _a = Dtor; let _b = Dtor; } fn main() { unsafe { execute(a) }; } ``` To address this issue, this PR adds an unwind edge to an abort block, so that the Rust example aborts. This is similar to how clang guards against double unwind (except clang calls terminate per C++ spec and we abort). The cost should be very small; it's an additional trap instruction (well, two for now, since we use TrapUnreachable, but that's a different issue) for each function with landing pads; if LLVM gains support to encode "abort/terminate" info directly in LSDA like GCC does, then it'll be free. It's an additional basic block though so compile time may be worse, so I'd like a perf run. r? `@ghost` `@rustbot` label: F-c_unwind
2 parents 9ab3225 + 25e1358 commit 4b4f53f

File tree

1 file changed

+1
-2
lines changed

1 file changed

+1
-2
lines changed

core/src/panicking.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
8787

8888
#[cfg(not(bootstrap))]
8989
#[cold]
90-
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
91-
#[track_caller]
90+
#[inline(never)]
9291
#[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function
9392
fn panic_no_unwind() -> ! {
9493
if cfg!(feature = "panic_immediate_abort") {

0 commit comments

Comments
 (0)