Handle inline asm in has_ffi_unwind_calls
This is required for the soundness of options(may_unwind)
This commit is contained in:
parent
7934bbdf84
commit
d3c580db21
5 changed files with 71 additions and 0 deletions
|
|
@ -1,4 +1,7 @@
|
|||
mir_transform_arithmetic_overflow = this arithmetic operation will overflow
|
||||
|
||||
mir_transform_asm_unwind_call = call to inline assembly that may unwind
|
||||
|
||||
mir_transform_const_defined_here = `const` item defined here
|
||||
|
||||
mir_transform_const_modify = attempting to modify a `const` item
|
||||
|
|
|
|||
|
|
@ -143,6 +143,13 @@ impl AssertLintKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_transform_asm_unwind_call)]
|
||||
pub(crate) struct AsmUnwindCall {
|
||||
#[label(mir_transform_asm_unwind_call)]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_transform_ffi_unwind_call)]
|
||||
pub(crate) struct FfiUnwindCall {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::InlineAsmOptions;
|
||||
use rustc_hir::def_id::{LOCAL_CRATE, LocalDefId};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::query::{LocalCrate, Providers};
|
||||
|
|
@ -46,6 +47,34 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
|
|||
continue;
|
||||
}
|
||||
let Some(terminator) = &block.terminator else { continue };
|
||||
|
||||
if let TerminatorKind::InlineAsm { options, .. } = &terminator.kind {
|
||||
if options.contains(InlineAsmOptions::MAY_UNWIND) {
|
||||
// We have detected an inline asm block that can possibly leak foreign unwind.
|
||||
//
|
||||
// Because the function body itself can unwind, we are not aborting this function call
|
||||
// upon unwind, so this call can possibly leak foreign unwind into Rust code if the
|
||||
// panic runtime linked is panic-abort.
|
||||
|
||||
let lint_root = body.source_scopes[terminator.source_info.scope]
|
||||
.local_data
|
||||
.as_ref()
|
||||
.unwrap_crate_local()
|
||||
.lint_root;
|
||||
let span = terminator.source_info.span;
|
||||
|
||||
tcx.emit_node_span_lint(
|
||||
FFI_UNWIND_CALLS,
|
||||
lint_root,
|
||||
span,
|
||||
errors::AsmUnwindCall { span },
|
||||
);
|
||||
|
||||
tainted = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let TerminatorKind::Call { func, .. } = &terminator.kind else { continue };
|
||||
|
||||
let ty = func.ty(body, tcx);
|
||||
|
|
|
|||
18
tests/ui/asm/may_unwind_ffi_unwind.rs
Normal file
18
tests/ui/asm/may_unwind_ffi_unwind.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Check that asm!() with options(may_unwind) is considered an FFI call by has_ffi_unwind_calls.
|
||||
|
||||
//@ check-fail
|
||||
//@ needs-asm-support
|
||||
//@ needs-unwind
|
||||
|
||||
#![feature(asm_unwind)]
|
||||
#![deny(ffi_unwind_calls)]
|
||||
|
||||
use std::arch::asm;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn asm_may_unwind() {
|
||||
asm!("", options(may_unwind));
|
||||
//~^ ERROR call to inline assembly that may unwind
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
14
tests/ui/asm/may_unwind_ffi_unwind.stderr
Normal file
14
tests/ui/asm/may_unwind_ffi_unwind.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error: call to inline assembly that may unwind
|
||||
--> $DIR/may_unwind_ffi_unwind.rs:14:5
|
||||
|
|
||||
LL | asm!("", options(may_unwind));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to inline assembly that may unwind
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/may_unwind_ffi_unwind.rs:8:9
|
||||
|
|
||||
LL | #![deny(ffi_unwind_calls)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue