about summary refs log tree commit diff
path: root/tests/codegen
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-07-18 04:27:51 +0200
committerGitHub <noreply@github.com>2025-07-18 04:27:51 +0200
commitaccf61dd42548bd5ec61d43f246b3eb499e980dd (patch)
tree31fad0f50ed48bd49c9d0b5451feeb9298ec856d /tests/codegen
parentb252014673d31f371757613a4ced13adfd6b304c (diff)
parent9c8ab891876b37aac458a7461d904fe593856745 (diff)
downloadrust-accf61dd42548bd5ec61d43f246b3eb499e980dd.tar.gz
rust-accf61dd42548bd5ec61d43f246b3eb499e980dd.zip
Rollup merge of #143293 - folkertdev:naked-function-kcfi, r=compiler-errors
fix `-Zsanitizer=kcfi` on `#[naked]` functions

fixes https://github.com/rust-lang/rust/issues/143266

With `-Zsanitizer=kcfi`, indirect calls happen via generated intermediate shim that forwards the call. The generated shim preserves the attributes of the original, including `#[unsafe(naked)]`. The shim is not a naked function though, and violates its invariants (like having a body that consists of a single `naked_asm!` call).

My fix here is to match on the `InstanceKind`, and only use `codegen_naked_asm` when the instance is not a `ReifyShim`. That does beg the question whether there are other `InstanceKind`s that could come up. As far as I can tell the answer is no: calling via `dyn` seems to work find, and `#[track_caller]` is disallowed in combination with `#[naked]`.

r? codegen
````@rustbot```` label +A-naked
cc ````@maurer```` ````@rcvalle````
Diffstat (limited to 'tests/codegen')
-rw-r--r--tests/codegen/sanitizer/kcfi/naked-function.rs47
1 files changed, 47 insertions, 0 deletions
diff --git a/tests/codegen/sanitizer/kcfi/naked-function.rs b/tests/codegen/sanitizer/kcfi/naked-function.rs
new file mode 100644
index 00000000000..2c8cdc919b8
--- /dev/null
+++ b/tests/codegen/sanitizer/kcfi/naked-function.rs
@@ -0,0 +1,47 @@
+//@ add-core-stubs
+//@ revisions: aarch64 x86_64
+//@ [aarch64] compile-flags: --target aarch64-unknown-none
+//@ [aarch64] needs-llvm-components: aarch64
+//@ [x86_64] compile-flags: --target x86_64-unknown-none
+//@ [x86_64] needs-llvm-components: x86
+//@ compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi -Cno-prepopulate-passes -Copt-level=0
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+struct Thing;
+trait MyTrait {
+    #[unsafe(naked)]
+    extern "C" fn my_naked_function() {
+        // the real function is defined
+        // CHECK: .globl
+        // CHECK-SAME: my_naked_function
+        naked_asm!("ret")
+    }
+}
+impl MyTrait for Thing {}
+
+// the shim calls the real function
+// CHECK-LABEL: define
+// CHECK-SAME: my_naked_function
+// CHECK-SAME: reify.shim.fnptr
+
+// CHECK-LABEL: main
+#[unsafe(no_mangle)]
+pub fn main() {
+    // Trick the compiler into generating an indirect call.
+    const F: extern "C" fn() = Thing::my_naked_function;
+
+    // main calls the shim function
+    // CHECK: call void
+    // CHECK-SAME: my_naked_function
+    // CHECK-SAME: reify.shim.fnptr
+    (F)();
+}
+
+// CHECK: declare !kcfi_type
+// CHECK-SAME: my_naked_function