Rollup merge of #128138 - folkertdev:asm-option-allowlist, r=lcnr
`#[naked]`: use an allowlist for allowed options on `asm!` in naked functions tracking issue: https://github.com/rust-lang/rust/issues/90957 this is mostly just a refactor, but using an allowlist (rather than a denylist) for which asm options are allowed in naked functions is a little safer. These options are disallowed because naked functions are effectively global asm, but defined using inline asm.
This commit is contained in:
commit
e76bb3fab6
6 changed files with 49 additions and 72 deletions
|
@ -2264,6 +2264,42 @@ bitflags::bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl InlineAsmOptions {
|
||||||
|
pub fn human_readable_names(&self) -> Vec<&'static str> {
|
||||||
|
let mut options = vec![];
|
||||||
|
|
||||||
|
if self.contains(InlineAsmOptions::PURE) {
|
||||||
|
options.push("pure");
|
||||||
|
}
|
||||||
|
if self.contains(InlineAsmOptions::NOMEM) {
|
||||||
|
options.push("nomem");
|
||||||
|
}
|
||||||
|
if self.contains(InlineAsmOptions::READONLY) {
|
||||||
|
options.push("readonly");
|
||||||
|
}
|
||||||
|
if self.contains(InlineAsmOptions::PRESERVES_FLAGS) {
|
||||||
|
options.push("preserves_flags");
|
||||||
|
}
|
||||||
|
if self.contains(InlineAsmOptions::NORETURN) {
|
||||||
|
options.push("noreturn");
|
||||||
|
}
|
||||||
|
if self.contains(InlineAsmOptions::NOSTACK) {
|
||||||
|
options.push("nostack");
|
||||||
|
}
|
||||||
|
if self.contains(InlineAsmOptions::ATT_SYNTAX) {
|
||||||
|
options.push("att_syntax");
|
||||||
|
}
|
||||||
|
if self.contains(InlineAsmOptions::RAW) {
|
||||||
|
options.push("raw");
|
||||||
|
}
|
||||||
|
if self.contains(InlineAsmOptions::MAY_UNWIND) {
|
||||||
|
options.push("may_unwind");
|
||||||
|
}
|
||||||
|
|
||||||
|
options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for InlineAsmOptions {
|
impl std::fmt::Debug for InlineAsmOptions {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
bitflags::parser::to_writer(self, f)
|
bitflags::parser::to_writer(self, f)
|
||||||
|
|
|
@ -1505,35 +1505,7 @@ impl<'a> State<'a> {
|
||||||
AsmArg::Options(opts) => {
|
AsmArg::Options(opts) => {
|
||||||
s.word("options");
|
s.word("options");
|
||||||
s.popen();
|
s.popen();
|
||||||
let mut options = vec![];
|
s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| {
|
||||||
if opts.contains(InlineAsmOptions::PURE) {
|
|
||||||
options.push("pure");
|
|
||||||
}
|
|
||||||
if opts.contains(InlineAsmOptions::NOMEM) {
|
|
||||||
options.push("nomem");
|
|
||||||
}
|
|
||||||
if opts.contains(InlineAsmOptions::READONLY) {
|
|
||||||
options.push("readonly");
|
|
||||||
}
|
|
||||||
if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) {
|
|
||||||
options.push("preserves_flags");
|
|
||||||
}
|
|
||||||
if opts.contains(InlineAsmOptions::NORETURN) {
|
|
||||||
options.push("noreturn");
|
|
||||||
}
|
|
||||||
if opts.contains(InlineAsmOptions::NOSTACK) {
|
|
||||||
options.push("nostack");
|
|
||||||
}
|
|
||||||
if opts.contains(InlineAsmOptions::ATT_SYNTAX) {
|
|
||||||
options.push("att_syntax");
|
|
||||||
}
|
|
||||||
if opts.contains(InlineAsmOptions::RAW) {
|
|
||||||
options.push("raw");
|
|
||||||
}
|
|
||||||
if opts.contains(InlineAsmOptions::MAY_UNWIND) {
|
|
||||||
options.push("may_unwind");
|
|
||||||
}
|
|
||||||
s.commasep(Inconsistent, &options, |s, &opt| {
|
|
||||||
s.word(opt);
|
s.word(opt);
|
||||||
});
|
});
|
||||||
s.pclose();
|
s.pclose();
|
||||||
|
|
|
@ -1298,35 +1298,7 @@ impl<'a> State<'a> {
|
||||||
AsmArg::Options(opts) => {
|
AsmArg::Options(opts) => {
|
||||||
s.word("options");
|
s.word("options");
|
||||||
s.popen();
|
s.popen();
|
||||||
let mut options = vec![];
|
s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| {
|
||||||
if opts.contains(ast::InlineAsmOptions::PURE) {
|
|
||||||
options.push("pure");
|
|
||||||
}
|
|
||||||
if opts.contains(ast::InlineAsmOptions::NOMEM) {
|
|
||||||
options.push("nomem");
|
|
||||||
}
|
|
||||||
if opts.contains(ast::InlineAsmOptions::READONLY) {
|
|
||||||
options.push("readonly");
|
|
||||||
}
|
|
||||||
if opts.contains(ast::InlineAsmOptions::PRESERVES_FLAGS) {
|
|
||||||
options.push("preserves_flags");
|
|
||||||
}
|
|
||||||
if opts.contains(ast::InlineAsmOptions::NORETURN) {
|
|
||||||
options.push("noreturn");
|
|
||||||
}
|
|
||||||
if opts.contains(ast::InlineAsmOptions::NOSTACK) {
|
|
||||||
options.push("nostack");
|
|
||||||
}
|
|
||||||
if opts.contains(ast::InlineAsmOptions::ATT_SYNTAX) {
|
|
||||||
options.push("att_syntax");
|
|
||||||
}
|
|
||||||
if opts.contains(ast::InlineAsmOptions::RAW) {
|
|
||||||
options.push("raw");
|
|
||||||
}
|
|
||||||
if opts.contains(ast::InlineAsmOptions::MAY_UNWIND) {
|
|
||||||
options.push("may_unwind");
|
|
||||||
}
|
|
||||||
s.commasep(Inconsistent, &options, |s, &opt| {
|
|
||||||
s.word(opt);
|
s.word(opt);
|
||||||
});
|
});
|
||||||
s.pclose();
|
s.pclose();
|
||||||
|
|
|
@ -244,22 +244,19 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
|
||||||
self.tcx.dcx().emit_err(NakedFunctionsOperands { unsupported_operands });
|
self.tcx.dcx().emit_err(NakedFunctionsOperands { unsupported_operands });
|
||||||
}
|
}
|
||||||
|
|
||||||
let unsupported_options: Vec<&'static str> = [
|
let supported_options =
|
||||||
(InlineAsmOptions::MAY_UNWIND, "`may_unwind`"),
|
InlineAsmOptions::RAW | InlineAsmOptions::NORETURN | InlineAsmOptions::ATT_SYNTAX;
|
||||||
(InlineAsmOptions::NOMEM, "`nomem`"),
|
let unsupported_options = asm.options.difference(supported_options);
|
||||||
(InlineAsmOptions::NOSTACK, "`nostack`"),
|
|
||||||
(InlineAsmOptions::PRESERVES_FLAGS, "`preserves_flags`"),
|
|
||||||
(InlineAsmOptions::PURE, "`pure`"),
|
|
||||||
(InlineAsmOptions::READONLY, "`readonly`"),
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.filter_map(|&(option, name)| if asm.options.contains(option) { Some(name) } else { None })
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if !unsupported_options.is_empty() {
|
if !unsupported_options.is_empty() {
|
||||||
self.tcx.dcx().emit_err(NakedFunctionsAsmOptions {
|
self.tcx.dcx().emit_err(NakedFunctionsAsmOptions {
|
||||||
span,
|
span,
|
||||||
unsupported_options: unsupported_options.join(", "),
|
unsupported_options: unsupported_options
|
||||||
|
.human_readable_names()
|
||||||
|
.into_iter()
|
||||||
|
.map(|name| format!("`{name}`"))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", "),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,7 +111,7 @@ unsafe extern "C" fn invalid_options() {
|
||||||
unsafe extern "C" fn invalid_options_continued() {
|
unsafe extern "C" fn invalid_options_continued() {
|
||||||
asm!("", options(readonly, nostack), options(pure));
|
asm!("", options(readonly, nostack), options(pure));
|
||||||
//~^ ERROR asm with the `pure` option must have at least one output
|
//~^ ERROR asm with the `pure` option must have at least one output
|
||||||
//~| ERROR asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
|
//~| ERROR asm options unsupported in naked functions: `pure`, `readonly`, `nostack`
|
||||||
//~| ERROR asm in naked functions must use `noreturn` option
|
//~| ERROR asm in naked functions must use `noreturn` option
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_fl
|
||||||
LL | asm!("", options(nomem, preserves_flags, noreturn));
|
LL | asm!("", options(nomem, preserves_flags, noreturn));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
|
error[E0787]: asm options unsupported in naked functions: `pure`, `readonly`, `nostack`
|
||||||
--> $DIR/naked-functions.rs:112:5
|
--> $DIR/naked-functions.rs:112:5
|
||||||
|
|
|
|
||||||
LL | asm!("", options(readonly, nostack), options(pure));
|
LL | asm!("", options(readonly, nostack), options(pure));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue