Reject unsupported naked functions

Transition unsupported naked functions future incompatibility lint into
an error:

* Naked functions must contain a single inline assembly block.
  Introduced as future incompatibility lint in 1.50 #79653.
  Change into an error fixes a soundness issue described in #32489.

* Naked functions must not use any forms of inline attribute.
  Introduced as future incompatibility lint in 1.56 #87652.
This commit is contained in:
Tomasz Miąsko 2022-01-21 00:00:00 +00:00
parent 84e918971d
commit 888332fee4
9 changed files with 182 additions and 295 deletions

View file

@ -1,42 +1,32 @@
// compile-flags: -C no-prepopulate-passes
// needs-asm-support
// only-x86_64
#![crate_type = "lib"]
#![feature(naked_functions)]
use std::arch::asm;
// CHECK: Function Attrs: naked
// CHECK-NEXT: define{{.*}}void @naked_empty()
#[no_mangle]
#[naked]
pub fn naked_empty() {
pub unsafe extern "C" fn naked_empty() {
// CHECK-NEXT: {{.+}}:
// CHECK-NEXT: ret void
// CHECK-NEXT: call void asm
// CHECK-NEXT: unreachable
asm!("ret",
options(noreturn));
}
// CHECK: Function Attrs: naked
// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_args_and_return(i64 %a, i64 %b)
#[no_mangle]
#[naked]
// CHECK-NEXT: define{{.*}}void @naked_with_args(i{{[0-9]+( %a)?}})
pub fn naked_with_args(a: isize) {
pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize {
// CHECK-NEXT: {{.+}}:
// CHECK: ret void
}
// CHECK: Function Attrs: naked
// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_return()
#[no_mangle]
#[naked]
pub fn naked_with_return() -> isize {
// CHECK-NEXT: {{.+}}:
// CHECK-NEXT: ret i{{[0-9]+}} 0
0
}
// CHECK: Function Attrs: naked
// CHECK-NEXT: define{{.*}}i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+( %a)?}})
#[no_mangle]
#[naked]
pub fn naked_with_args_and_return(a: isize) -> isize {
// CHECK-NEXT: {{.+}}:
// CHECK: ret i{{[0-9]+}} 0
0
// CHECK-NEXT: call void asm
// CHECK-NEXT: unreachable
asm!("lea rax, [rdi + rsi]",
"ret",
options(noreturn));
}

View file

@ -7,7 +7,6 @@
use std::arch::asm;
#[inline(always)]
#[naked]
#[no_mangle]
pub unsafe extern "C" fn f() {

View file

@ -32,8 +32,7 @@ pub unsafe extern "C" fn patterns(
#[naked]
pub unsafe extern "C" fn inc(a: u32) -> u32 {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
//~^ ERROR naked functions must contain a single asm block
a + 1
//~^ ERROR referencing function parameters is not allowed in naked functions
}
@ -42,21 +41,18 @@ pub unsafe extern "C" fn inc(a: u32) -> u32 {
pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
asm!("/* {0} */", in(reg) a, options(noreturn));
//~^ ERROR referencing function parameters is not allowed in naked functions
//~| WARN only `const` and `sym` operands are supported in naked functions
//~| WARN this was previously accepted
//~| ERROR only `const` and `sym` operands are supported in naked functions
}
#[naked]
pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
//~^ ERROR naked functions must contain a single asm block
(|| a + 1)()
}
#[naked]
pub unsafe extern "C" fn unsupported_operands() {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
//~^ ERROR naked functions must contain a single asm block
let mut a = 0usize;
let mut b = 0usize;
let mut c = 0usize;
@ -65,11 +61,9 @@ pub unsafe extern "C" fn unsupported_operands() {
const F: usize = 0usize;
static G: usize = 0usize;
asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
//~^ WARN asm in naked functions must use `noreturn` option
//~| WARN this was previously accepted
//~^ ERROR asm in naked functions must use `noreturn` option
in(reg) a,
//~^ WARN only `const` and `sym` operands are supported in naked functions
//~| WARN this was previously accepted
//~^ ERROR only `const` and `sym` operands are supported in naked functions
inlateout(reg) b,
inout(reg) c,
lateout(reg) d,
@ -81,31 +75,25 @@ pub unsafe extern "C" fn unsupported_operands() {
#[naked]
pub extern "C" fn missing_assembly() {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
//~^ ERROR naked functions must contain a single asm block
}
#[naked]
pub extern "C" fn too_many_asm_blocks() {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
//~^ ERROR naked functions must contain a single asm block
asm!("");
//~^ WARN asm in naked functions must use `noreturn` option
//~| WARN this was previously accepted
//~^ ERROR asm in naked functions must use `noreturn` option
asm!("");
//~^ WARN asm in naked functions must use `noreturn` option
//~| WARN this was previously accepted
//~^ ERROR asm in naked functions must use `noreturn` option
asm!("");
//~^ WARN asm in naked functions must use `noreturn` option
//~| WARN this was previously accepted
//~^ ERROR asm in naked functions must use `noreturn` option
asm!("", options(noreturn));
}
pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
#[naked]
pub extern "C" fn inner(y: usize) -> usize {
//~^ WARN naked functions must contain a single asm block
//~| WARN this was previously accepted
//~^ ERROR naked functions must contain a single asm block
*&y
//~^ ERROR referencing function parameters is not allowed in naked functions
}
@ -115,18 +103,15 @@ pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
#[naked]
unsafe extern "C" fn invalid_options() {
asm!("", options(nomem, preserves_flags, noreturn));
//~^ WARN asm options unsupported in naked functions: `nomem`, `preserves_flags`
//~| WARN this was previously accepted
//~^ ERROR asm options unsupported in naked functions: `nomem`, `preserves_flags`
}
#[naked]
unsafe extern "C" fn invalid_options_continued() {
asm!("", options(readonly, nostack), options(pure));
//~^ ERROR asm with the `pure` option must have at least one output
//~| WARN asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
//~| WARN this was previously accepted
//~| WARN asm in naked functions must use `noreturn` option
//~| WARN this was previously accepted
//~| ERROR asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
//~| ERROR asm in naked functions must use `noreturn` option
}
#[naked]
@ -177,38 +162,32 @@ pub unsafe extern "C" fn inline_none() {
#[naked]
#[inline]
//~^ WARN naked functions cannot be inlined
//~| WARN this was previously accepted
//~^ ERROR naked functions cannot be inlined
pub unsafe extern "C" fn inline_hint() {
asm!("", options(noreturn));
}
#[naked]
#[inline(always)]
//~^ WARN naked functions cannot be inlined
//~| WARN this was previously accepted
//~^ ERROR naked functions cannot be inlined
pub unsafe extern "C" fn inline_always() {
asm!("", options(noreturn));
}
#[naked]
#[inline(never)]
//~^ WARN naked functions cannot be inlined
//~| WARN this was previously accepted
//~^ ERROR naked functions cannot be inlined
pub unsafe extern "C" fn inline_never() {
asm!("", options(noreturn));
}
#[naked]
#[inline]
//~^ WARN naked functions cannot be inlined
//~| WARN this was previously accepted
//~^ ERROR naked functions cannot be inlined
#[inline(always)]
//~^ WARN naked functions cannot be inlined
//~| WARN this was previously accepted
//~^ ERROR naked functions cannot be inlined
#[inline(never)]
//~^ WARN naked functions cannot be inlined
//~| WARN this was previously accepted
//~^ ERROR naked functions cannot be inlined
pub unsafe extern "C" fn inline_all() {
asm!("", options(noreturn));
}

View file

@ -1,5 +1,5 @@
error: asm with the `pure` option must have at least one output
--> $DIR/naked-functions.rs:124:14
--> $DIR/naked-functions.rs:111:14
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
@ -29,66 +29,54 @@ LL | P { x, y }: P,
| ^^^^^^^^^^
error: referencing function parameters is not allowed in naked functions
--> $DIR/naked-functions.rs:37:5
--> $DIR/naked-functions.rs:36:5
|
LL | a + 1
| ^
|
= help: follow the calling convention in asm block to use parameters
warning: naked functions must contain a single asm block
error[E0787]: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:34:1
|
LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
LL | |
LL | |
LL | | a + 1
| | ----- non-asm is unsupported in naked functions
LL | |
LL | | }
| |_^
|
= note: `#[warn(unsupported_naked_functions)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
error: referencing function parameters is not allowed in naked functions
--> $DIR/naked-functions.rs:43:31
--> $DIR/naked-functions.rs:42:31
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^
|
= help: follow the calling convention in asm block to use parameters
warning: only `const` and `sym` operands are supported in naked functions
--> $DIR/naked-functions.rs:43:23
error[E0787]: only `const` and `sym` operands are supported in naked functions
--> $DIR/naked-functions.rs:42:23
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:50:1
error[E0787]: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:48:1
|
LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
LL | |
LL | |
LL | | (|| a + 1)()
| | ------------ non-asm is unsupported in naked functions
LL | | }
| |_^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: only `const` and `sym` operands are supported in naked functions
--> $DIR/naked-functions.rs:70:10
error[E0787]: only `const` and `sym` operands are supported in naked functions
--> $DIR/naked-functions.rs:65:10
|
LL | in(reg) a,
| ^^^^^^^^^
...
LL |
LL | inlateout(reg) b,
| ^^^^^^^^^^^^^^^^
LL | inout(reg) c,
@ -97,31 +85,24 @@ LL | lateout(reg) d,
| ^^^^^^^^^^^^^^
LL | out(reg) e,
| ^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:67:5
error[E0787]: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:63:5
|
LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
LL | |
LL | |
LL | | in(reg) a,
LL | |
... |
LL | | sym G,
LL | | );
| |_____^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:57:1
error[E0787]: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:54:1
|
LL | / pub unsafe extern "C" fn unsupported_operands() {
LL | |
LL | |
LL | | let mut a = 0usize;
| | ------------------- non-asm is unsupported in naked functions
LL | | let mut b = 0usize;
@ -136,123 +117,90 @@ LL | | let mut e = 0usize;
LL | | );
LL | | }
| |_^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:83:1
error[E0787]: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:77:1
|
LL | / pub extern "C" fn missing_assembly() {
LL | |
LL | |
LL | | }
| |_^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:92:5
error[E0787]: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:84:5
|
LL | asm!("");
| ^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:95:5
error[E0787]: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:86:5
|
LL | asm!("");
| ^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:98:5
error[E0787]: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:88:5
|
LL | asm!("");
| ^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:89:1
error[E0787]: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:82:1
|
LL | / pub extern "C" fn too_many_asm_blocks() {
LL | |
LL | | asm!("");
LL | |
LL | | asm!("");
... |
| | -------- multiple asm blocks are unsupported in naked functions
LL | |
LL | | asm!("");
| | -------- multiple asm blocks are unsupported in naked functions
... |
LL | | asm!("");
| | -------- multiple asm blocks are unsupported in naked functions
... |
LL | |
LL | | asm!("", options(noreturn));
| | --------------------------- multiple asm blocks are unsupported in naked functions
LL | | }
| |_^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
error: referencing function parameters is not allowed in naked functions
--> $DIR/naked-functions.rs:109:11
--> $DIR/naked-functions.rs:97:11
|
LL | *&y
| ^
|
= help: follow the calling convention in asm block to use parameters
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:106:5
error[E0787]: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:95:5
|
LL | / pub extern "C" fn inner(y: usize) -> usize {
LL | |
LL | |
LL | | *&y
| | --- non-asm is unsupported in naked functions
LL | |
LL | | }
| |_____^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm options unsupported in naked functions: `nomem`, `preserves_flags`
--> $DIR/naked-functions.rs:117:5
error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags`
--> $DIR/naked-functions.rs:105:5
|
LL | asm!("", options(nomem, preserves_flags, noreturn));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
--> $DIR/naked-functions.rs:124:5
error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
--> $DIR/naked-functions.rs:111:5
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:124:5
error[E0787]: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:111:5
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: Rust ABI is unsupported in naked functions
--> $DIR/naked-functions.rs:133:15
--> $DIR/naked-functions.rs:118:15
|
LL | pub unsafe fn default_abi() {
| ^^^^^^^^^^^
@ -260,64 +208,47 @@ LL | pub unsafe fn default_abi() {
= note: `#[warn(undefined_naked_function_abi)]` on by default
warning: Rust ABI is unsupported in naked functions
--> $DIR/naked-functions.rs:139:15
--> $DIR/naked-functions.rs:124:15
|
LL | pub unsafe fn rust_abi() {
| ^^^^^^^^
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:179:1
error: naked functions cannot be inlined
--> $DIR/naked-functions.rs:164:1
|
LL | #[inline]
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
error: naked functions cannot be inlined
--> $DIR/naked-functions.rs:171:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
error: naked functions cannot be inlined
--> $DIR/naked-functions.rs:178:1
|
LL | #[inline(never)]
| ^^^^^^^^^^^^^^^^
error: naked functions cannot be inlined
--> $DIR/naked-functions.rs:185:1
|
LL | #[inline]
| ^^^^^^^^^
error: naked functions cannot be inlined
--> $DIR/naked-functions.rs:187:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:195:1
error: naked functions cannot be inlined
--> $DIR/naked-functions.rs:189:1
|
LL | #[inline(never)]
| ^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:203:1
|
LL | #[inline]
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:206:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:209:1
|
LL | #[inline(never)]
| ^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
error: aborting due to 8 previous errors; 23 warnings emitted
error: aborting due to 29 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0787`.