Skip to content

Footgun with catch_unwind when catching panic-on-drop types #86027

Open
@m-ou-se

Description

@m-ou-se

Originally reported by @SabrinaJewson in #85927


catch_unwind(code) is often used to make sure no panics from code can cause further unwinding/panics. However, when catching a panic with a payload that panics on Drop, most usages of catch_unwind(code) will still result in further unwinding and often unsoundness.

struct Bomb;

impl Drop for Bomb {
    fn drop(&mut self) {
        panic!();
    }
}

std::panic::panic_any(Bomb);

Example in rustc (found by @mystor):

let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t)))
.unwrap_or_else(|_| process::abort());

Here, the Result containing the panic payload is dropped before abort() 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:

let exit_code = panic::catch_unwind(main);
sys_common::rt::cleanup();
exit_code.unwrap_or(101) as isize
}

fn main() {
    std::panic::panic_any(Bomb);
}
thread 'main' panicked at 'Box<Any>', src/main.rs:12:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at 'explicit panic', src/main.rs:7:9
fatal runtime error: failed to initiate panic, error 5
abort (core dumped)

And another case in the proc_macro bridge:

panic::catch_unwind(panic::AssertUnwindSafe(call_method))
.map_err(PanicMessage::from)

#[proc_macro]
pub fn hey(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
    std::panic::panic_any(Bomb);
}
thread 'rustc' panicked at 'explicit panic', src/lib.rs:5:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-runtimeArea: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflowsP-mediumMedium priorityT-langRelevant to the language team, which will review and decide on the PR/issue.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions