惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V2EX - 技术
V2EX - 技术
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
Schneier on Security
S
Securelist
P
Privacy & Cybersecurity Law Blog
Scott Helme
Scott Helme
T
Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
L
LINUX DO - 热门话题
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
量子位
博客园 - Franky
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Latest news
Latest news
T
Troy Hunt's Blog
N
News | PayPal Newsroom
Google Online Security Blog
Google Online Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
N
Netflix TechBlog - Medium
小众软件
小众软件
P
Palo Alto Networks Blog
Spread Privacy
Spread Privacy
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
WordPress大学
WordPress大学
L
Lohrmann on Cybersecurity
L
LINUX DO - 最新话题
D
Darknet – Hacking Tools, Hacker News & Cyber Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Last Watchdog
The Last Watchdog
S
Security @ Cisco Blogs
P
Privacy International News Feed
Last Week in AI
Last Week in AI
Microsoft Security Blog
Microsoft Security Blog
T
Tailwind CSS Blog
博客园_首页
云风的 BLOG
云风的 BLOG
V
Vulnerabilities – Threatpost
D
DataBreaches.Net
Recent Announcements
Recent Announcements
酷 壳 – CoolShell
酷 壳 – CoolShell
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
罗磊的独立博客
Engineering at Meta
Engineering at Meta
Forbes - Security
Forbes - Security
T
Tenable Blog

Rust Blog

Security Advisory for Cargo (CVE-2026-5223) | Rust Blog Security Advisory for Cargo (CVE-2026-5222) | Rust Blog Project goals update — April 2026 (end of 2025H2) | Rust Blog Rust is participating in Outreachy | Rust Blog Raising the baseline for the `nvptx64-nvidia-cuda` target | Rust Blog Announcing Google Summer of Code 2026 selected projects | Rust Blog Announcing Rust 1.95.0 | Rust Blog docs.rs: building fewer targets by default | Rust Blog Changes to WebAssembly targets and handling undefined symbols | Rust Blog Announcing Rust 1.94.1 | Rust Blog Security advisory for Cargo | Rust Blog What we heard about Rust's challenges | Rust Blog Call for Testing: Build Dir Layout v2 | Rust Blog Announcing rustup 1.29.0 | Rust Blog Announcing Rust 1.94.0 | Rust Blog 2025 State of Rust Survey Results | Rust Blog Rust debugging survey 2026 | Rust Blog Update on the October 15, 2018 incident on crates.io Announcing Rust 1.29.2 Announcing Rust 1.29 Announcing Rust 1.28 What is Rust 2018? Announcing Rust 1.27.2 Announcing Rust 1.27.1 Security Advisory for rustdoc Announcing Rust 1.27 Announcing Rust 1.26.2 Announcing Rust 1.26.1 Rust turns three Announcing Rust 1.26 The Rust Team All Hands in Berlin: a Recap Increasing Rust’s Reach 2018 Announcing Rust 1.25 Rust's 2018 roadmap Announcing Rust 1.24.1 Announcing Rust 1.24 The 2018 Rust Event Lineup Announcing Rust 1.23 New Year's Rust: A Call for Community Blogposts Rust in 2017: what we achieved Announcing Rust 1.22 (and 1.22.1) Fearless Concurrency in Firefox Quantum Announcing Rust 1.21 impl Future for Rust Rust 2017 Survey Results Announcing Rust 1.20 Announcing Rust 1.19 The 2017 Rust Conference Lineup Rust's 2017 roadmap, six months in Increasing Rust’s Reach Announcing Rust 1.18 Two years of Rust The Rust Libz Blitz Launching the 2017 State of Rust Survey Announcing Rust 1.17 Announcing Rust 1.16 Rust's language ergonomics initiative Announcing Rust 1.15.1 Rust's 2017 roadmap Announcing Rust 1.15 Announcing Rust 1.14 Announcing the First Underhanded Rust Contest Announcing Rust 1.13 Announcing Rust 1.12.1 Announcing Rust 1.12 Incremental Compilation Announcing Rust 1.11 Shape of errors to come The 2016 Rust Conference Lineup Announcing Rust 1.10 State of Rust Survey 2016 Announcing Rust 1.9 One year of Rust Taking Rust everywhere with rustup Launching the 2016 State of Rust Survey Cargo: predictable dependency management Introducing MIR Announcing Rust 1.8 Announcing Rust 1.7 Announcing Rust 1.6 Announcing Rust 1.5 Announcing Rust 1.4 Announcing Rust 1.3 Rust in 2016 Announcing Rust 1.2 Rust 1.1 stable, the Community Subteam, and RustCamp Announcing Rust 1.0 Abstraction without overhead: traits in Rust Rust Once, Run Everywhere Mixing matching, mutation, and moves in Rust Fearless Concurrency with Rust Announcing Rust 1.0 Beta Announcing Rust 1.0.0.alpha.2 Rust 1.0: status report and final timeline Announcing Rust 1.0 Alpha Rust 1.0: Scheduling the trains Yehuda Katz and Steve Klabnik are joining the Rust Core Team Cargo: Rust's community crate host Stability as a Deliverable Road to Rust 1.0
Announcing the first FFI-unwind project design meeting | Inside Rust Blog
Kyle Strand, Niko Matsakis, and Amanieu d'Antras on behalf · 2020-02-27 · via Rust Blog

The FFI-unwind project group, announced in this RFC, is working to extend the language to support unwinding that crosses FFI boundaries.

We have reached our first technical decision point, on a question we have been discussing internally for quite a while. This blog post lays out the arguments on each side of the issue and invites the Rust community to join us at an upcoming meeting to help finalize our decision, which will be formalized and published as our first language-change RFC. This RFC will propose an "MVP" specification for well-defined cross-language unwinding.

The meeting will be on March 2nd.

Background: what is unwinding?

Exceptions are a familiar control flow mechanism in many programming languages. They are particularly commonplace in managed languages such as Java, but they are also part of the C++ language, which introduced them to the world of unmanaged systems programming.

When an exception is thrown, the runtime unwinds the stack, essentially traversing it backwards and calling clean-up or error-recovery code such as destructors or catch blocks.

Compilers may implement their own unwinding mechanisms, but in native code such as Rust binaries, the mechanism is more commonly provided by the platform ABI.

It is well known that Rust does not have exceptions as such. But Rust does support unwinding! There are two scenarios that will cause unwinding to occur:

  • By default, Rust's panic!() unwinds the stack.
  • Using FFI, Rust can call functions in other languages (such as C++) that can unwind the stack.
    • There are some special cases where C libraries can actually cause unwinding. For instance, on Microsoft platforms, longjmp is implemented as "forced unwinding" (see below)

Currently, when foreign (non-Rust) code invokes Rust code, the behavior of a panic!() unwind that "escapes" from Rust is explicitly undefined. Similarly, when Rust calls a foreign function that unwinds, the behavior once the unwind operation encounters Rust frames is undefined. The primary reason for this is to ensure that Rust implementations may use their own unwinding mechanism, which may not be compatible with the platform-provided "native" unwinding mechanism. Currently, however, rustc uses the native mechanism, and there are no plans to change this.

Forced unwinding

Platform ABIs can define a special kind of unwinding called "forced unwinding." This type of unwinding works regardless of whether the code being unwound supports unwinding or not. However, destructors may not be executed if the frames being unwound do not have unwinding support.

There are two common examples of forced unwinding:

  • On Windows platforms, longjmp is implemented as a forced unwind.
  • On glibc Linux, pthread_exit and pthread_cancel are implemented as a forced unwind.
    • In fact, pthread_cancel can cause all manner of C functions to unwind, including common functions like read and write. (For a complete list, search for "cancellation points" in the pthreads man page.)

Requirements for any cross-language unwinding specification

  • Unwinding between Rust functions (and in particular unwinding of Rust panics) may not necessarily use the system unwinding mechanism
    • In practice, we do use the system mechanism today, but we would like to reserve the freedom to change this.
  • If you enable -Cpanic=abort, we are able to optimize the size of binaries to remove most code related to unwinding.
    • Even with -Cpanic=unwind it should be possible to optimize away code when unwinding is known to never occur.
    • In practice, most "C" functions are never expected to unwind (because they are written in C, for example, and not in C++).
      • However, because unwinding is now part of most system ABIs, even C functions can unwind — most notably cancellation points triggered by pthread_cancel.
  • Changing the behavior from -Cpanic=unwind to -Cpanic=abort should not cause Undefined Behavior.
    • However, this may not be tenable, or at least not without making binaries much larger. See the discussion below for more details.
    • It may, of course, cause programs to abort that used to execute successfully. This could occur if a panic would've been caught and recovered.
  • We cannot change the ABI (the "C" in extern "C") of functions in the libc crate, because this would be a breaking change: function pointers of different ABIs have different types.
    • This is relevant for the libc functions which may perform forced unwinding when pthread_cancel is called.

The primary question: introduce a new ABI, or let the "C" ABI permit unwinding?

The core question that we would like to decide is whether the "C" ABI, as defined by Rust, should permit unwinding.

This is not a question we expected to be debating. We've long declared that unwinding through Rust's "C" ABI is undefined behavior. In part, this is because nobody had spent the time to figure out what the correct behavior would be, or how to implement it, although (as we'll see shortly) there are other good reasons for this choice.

In any case, in PR #65646, @Amanieu proposed that we could, in fact, simply define the behavior of unwinding across "C" boundaries. In discussing this, discovered that the question of whether the "C" ABI should permit unwinding was less clear-cut than we had assumed.

If the "C" ABI does not permit unwinding, a new ABI, called "C unwind", will be introduced specifically to support unwinding.

Three specific proposals

The project group has narrowed the design space down to three specific proposals. Two of these introduce the new "C unwind" ABI, and one does not.

Each proposal specifies the behavior of each type of unwind (Rust panic!, foreign (e.g. C++), and forced (e.g. pthread_exit)) when it encounters an ABI boundary under either the panic=unwind or panic=abort compile-mode.

Note that currently, catch_unwind does not intercept foreign unwinding (forced or unforced), and our initial RFCs will not change that. We may decide at a later date to define a way for Rust code to intercept foreign exceptions.

Throughout, the unwind generated by panic! will be referred to as panic-unwind.

Proposal 1: Introduce "C unwind", minimal specification

  • "C" ABI boundary, panic=<any>
    • panic-unwind: program aborts
    • forced unwinding, no destructors: unwind behaves normally
    • other foreign unwinding: undefined behavior
  • "C unwind" ABI boundary
    • With panic=unwind: all types of unwinding behave normally
    • With panic=abort: all types of unwinding abort the program

This proposal provides 2 ABIs, each suited for different purposes: you would generally use extern "C" when interacting with C APIs (making sure to avoid destructors where longjmp might be used), and extern "C unwind" when interacting with C++ APIs. The main advantage of this proposal is that switching between panic=unwind and panic=abort does not introduce UB if you have correctly marked all potential unwinding calls as "C unwind" (your program will abort instead).

Proposal 2: Introduce "C unwind", forced unwinding always permitted

This is the same as the previous design, except that when compiled with panic=abort, forced unwinding would not be intercepted at "C unwind" ABI boundaries; that is, they would behave normally (though still UB if there are any destructors), without causing the program to abort. panic-unwind and non-forced foreign exceptions would still cause the program to abort.

The advantage of treating forced unwinding differently is that it reduces portability incompatibilities. Specifically, it ensures that using "C unwind" cannot cause longjmp or pthread_exit to stop working (abort the program) when the target platform and/or compile flags are changed. With proposal 1, longjmp will be able to cross "C unwind" boundaries except on Windows with MSVC under panic=abort, and pthread_exit will work inside "C unwind" functions except when linked with glibc under panic=abort. The downside of this proposal is that the abort stubs around "C unwind" calls in panic=abort become more complicated since they need to distinguish between different types of foreign exceptions.

Proposal 3: No new ABI

  • panic=unwind: unwind behaves normally
  • panic=abort:
    • panic-unwind: does not exist; panic! aborts the program
    • forced unwinding, no destructors: unwind behaves normally
    • other foreign unwinding: undefined behavior

The main advantage of this proposal is its simplicity: there is only one ABI and the behavior of panic=abort is identical to that of -fno-exceptions in C++. However this comes with the downside that switching to panic=abort may in some cases introduce UB (though only in unsafe code) if FFI calls unwind through Rust code.

Another advantage is that forced unwinding from existing functions defined in the libc crate such as pthread_exit and longjmp will be able to unwind frames with destructors when compiled with panic=unwind, which is not possible with the other proposals.

Comparison table for the proposed designs

In this table, "UB" stands for "undefined behavior". We believe that all of these instances of undefined behavior could be detected at runtime, but the code to do so would impose an undesirable code-size penalty, entirely negating the optimizations made possible by using panic=unwind or the non-unwinding "C" ABI. This code would therefore only be appropriate for debug builds. Additionally, the complexity of implementing such checks may outweigh their benefits.

Note that unwinding through a frame that has destructors without running those destructors (e.g. because they have been optimized out by panic=abort) is always undefined behavior.

panic-unwind Forced unwind, no destructors Forced unwind with destructors Other foreign unwind
Proposals 1 & 2, "C" boundary, panic=unwind abort unwind UB UB
Proposals 1 & 2, "C" boundary, panic=abort panic! aborts (no unwinding occurs) unwind UB UB
Proposals 1 & 2, "C unwind" boundary, panic=unwind unwind unwind unwind unwind
Proposal 1, "C unwind" boundary, panic=abort panic! aborts abort abort abort
Proposal 2, "C unwind" boundary, panic=abort panic! aborts unwind UB abort
Proposal 3, "C" boundary, panic=unwind unwind unwind unwind unwind
Proposal 3, "C" boundary, panic=abort panic! aborts unwind UB UB