Skip to content

Commit 2754e75

Browse files
committed
Handle inline asm in has_ffi_unwind_calls
This is required for the soundness of options(may_unwind)
1 parent 473b5ee commit 2754e75

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

compiler/rustc_mir_transform/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
mir_transform_arithmetic_overflow = this arithmetic operation will overflow
2+
3+
mir_transform_asm_unwind_call = call to inline assembly that may unwind
4+
25
mir_transform_const_defined_here = `const` item defined here
36
47
mir_transform_const_modify = attempting to modify a `const` item

compiler/rustc_mir_transform/src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ impl AssertLintKind {
143143
}
144144
}
145145

146+
#[derive(LintDiagnostic)]
147+
#[diag(mir_transform_asm_unwind_call)]
148+
pub(crate) struct AsmUnwindCall {
149+
#[label(mir_transform_asm_unwind_call)]
150+
pub span: Span,
151+
}
152+
146153
#[derive(LintDiagnostic)]
147154
#[diag(mir_transform_ffi_unwind_call)]
148155
pub(crate) struct FfiUnwindCall {

compiler/rustc_mir_transform/src/ffi_unwind_calls.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_abi::ExternAbi;
2+
use rustc_ast::InlineAsmOptions;
23
use rustc_hir::def_id::{LOCAL_CRATE, LocalDefId};
34
use rustc_middle::mir::*;
45
use rustc_middle::query::{LocalCrate, Providers};
@@ -46,6 +47,34 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
4647
continue;
4748
}
4849
let Some(terminator) = &block.terminator else { continue };
50+
51+
if let TerminatorKind::InlineAsm { options, .. } = &terminator.kind {
52+
if options.contains(InlineAsmOptions::MAY_UNWIND) {
53+
// We have detected an inline asm block that can possibly leak foreign unwind.
54+
//
55+
// Because the function body itself can unwind, we are not aborting this function call
56+
// upon unwind, so this call can possibly leak foreign unwind into Rust code if the
57+
// panic runtime linked is panic-abort.
58+
59+
let lint_root = body.source_scopes[terminator.source_info.scope]
60+
.local_data
61+
.as_ref()
62+
.unwrap_crate_local()
63+
.lint_root;
64+
let span = terminator.source_info.span;
65+
66+
tcx.emit_node_span_lint(
67+
FFI_UNWIND_CALLS,
68+
lint_root,
69+
span,
70+
errors::AsmUnwindCall { span },
71+
);
72+
73+
tainted = true;
74+
}
75+
continue;
76+
}
77+
4978
let TerminatorKind::Call { func, .. } = &terminator.kind else { continue };
5079

5180
let ty = func.ty(body, tcx);

0 commit comments

Comments
 (0)