Skip to content

ICE: #[naked] functions should always terminate with an asm! block #143266

@matthiaskrgr

Description

@matthiaskrgr

auto-reduced (treereduce-rust):

//@compile-flags: -Zsanitizer=kcfi -Cpanic=abort
//

#![feature(abi_custom)]

use std::arch::{asm, global_asm, naked_asm};

#[unsafe(naked)]
unsafe extern "custom" fn double() {
    naked_asm!("add rax, rax", "ret");
}

unsafe extern "custom" {}

struct Thing(u64);

trait BitwiseNot {
    #[unsafe(naked)]
    unsafe extern "custom" fn bitwise_not() {
        naked_asm!("\0\x00\u{0}\u{0}", "ret");
    }
}

impl BitwiseNot for Thing {}

#[unsafe(naked)]
unsafe extern "C" fn const_generic<const N: u64>() {
    naked_asm!(
        "mov rax, {}",
        "ret",
        const N,
    );
}

pub fn main() {

    let mut x: u64 = 42;
    unsafe { asm!("call {}", sym Thing::bitwise_not, inout("rax") x) };
}
original code

original:

// Test that `extern "custom"` functions can be called from assembly, and defined using a naked
// function, and `global_asm!` with an `extern "custom"` block.
//
//@ run-pass
//@ only-x86_64
#![feature(abi_custom)]

use std::arch::{asm, global_asm, naked_asm};

#[unsafe(naked)]
unsafe extern "custom" fn double() {
    naked_asm!("add rax, rax", "ret");
}

global_asm!(
    // work around macOS prefixing symbols with _
    "    .globl  {0}",
    "{0}:",
    "    add     rax, 1",
    "    ret",
    sym increment,
);

unsafe extern "custom" {
    fn increment();
}

#[repr(transparent)]
struct Thing(u64);

impl Thing {
    #[unsafe(naked)]
    unsafe extern "custom" fn is_even() {
        naked_asm!("test al, 1", "sete al", "ret");
    }
}

trait BitwiseNot {
    #[unsafe(naked)]
    unsafe extern "custom" fn bitwise_not() {
        naked_asm!("\0\x00\u{0}\u{0}", "ret");
    }
}

impl BitwiseNot for Thing {}

#[unsafe(naked)]
unsafe extern "C" fn const_generic<const N: u64>() {
    naked_asm!(
        "mov rax, {}",
        "ret",
        const N,
    );
}

pub fn main() {
    let mut x: u64 = 21;
    unsafe { asm!("call {}", sym double, inout("rax") x) };
    assert_eq!(x, 42);

    let mut x: u64 = 41;
    unsafe { asm!("call {}", sym increment, inout("rax") x) };
    assert_eq!(x, 42);

    let mut x: u8;
    unsafe { asm!("call {}", sym Thing::is_even, inout("al") 42u8 => x) };
    assert!(x != 0);

    let mut x: u64 = 42;
    unsafe { asm!("call {}", sym Thing::bitwise_not, inout("rax") x) };
    assert_eq!(x, !42);

    // Create and call in `asm!` an `extern "custom"` function pointer.
    fn caller(f: unsafe extern "custom" fn(), mut x: u64) -> u64 {
        unsafe { asm!("call {}", in(reg) f, inout("rax") x) };
        x
    }

    assert_eq!(caller(double, 2), 4);

    let x: u64;
    unsafe { asm!("call {}", sym const_generic::<42>, out("rax") x) };
    assert_eq!(x, 42);

    let x: u64;
    unsafe { asm!("call {}", sym const_generic::<84>, out("rax") x) };
    assert_eq!(x, 84);
}

Version information

rustc 1.90.0-nightly (f26e58023 2025-06-30)
binary: rustc
commit-hash: f26e58023071e71636a3c72ac3a2bf89b1f76706
commit-date: 2025-06-30
host: x86_64-unknown-linux-gnu
release: 1.90.0-nightly
LLVM version: 20.1.7

Command:
/home/matthias/.rustup/toolchains/master/bin/rustc -Zsanitizer=kcfi -Cpanic=abort

Program output

warning: unused import: `global_asm`
 --> /tmp/icemaker_global_tempdir.L3dNdrnvcGlo/rustc_testrunner_tmpdir_reporting.8ehK9SvmHkij/mvce.rs:5:22
  |
5 | use std::arch::{asm, global_asm, naked_asm};
  |                      ^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: value assigned to `x` is never read
  --> /tmp/icemaker_global_tempdir.L3dNdrnvcGlo/rustc_testrunner_tmpdir_reporting.8ehK9SvmHkij/mvce.rs:37:67
   |
37 |     unsafe { asm!("call {}", sym Thing::bitwise_not, inout("rax") x) };
   |                                                                   ^
   |
   = help: maybe it is overwritten before being read?
   = note: `#[warn(unused_assignments)]` on by default

warning: function `double` is never used
 --> /tmp/icemaker_global_tempdir.L3dNdrnvcGlo/rustc_testrunner_tmpdir_reporting.8ehK9SvmHkij/mvce.rs:8:27
  |
8 | unsafe extern "custom" fn double() {
  |                           ^^^^^^
  |
  = note: `#[warn(dead_code)]` on by default

warning: field `0` is never read
  --> /tmp/icemaker_global_tempdir.L3dNdrnvcGlo/rustc_testrunner_tmpdir_reporting.8ehK9SvmHkij/mvce.rs:14:14
   |
14 | struct Thing(u64);
   |        ----- ^^^
   |        |
   |        field in this struct
   |
   = help: consider removing this field

warning: function `const_generic` is never used
  --> /tmp/icemaker_global_tempdir.L3dNdrnvcGlo/rustc_testrunner_tmpdir_reporting.8ehK9SvmHkij/mvce.rs:26:22
   |
26 | unsafe extern "C" fn const_generic<const N: u64>() {
   |                      ^^^^^^^^^^^^^

error: internal compiler error: /rustc-dev/f26e58023071e71636a3c72ac3a2bf89b1f76706/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs:40:9: #[naked] functions should always terminate with an asm! block


thread 'rustc' panicked at /rustc-dev/f26e58023071e71636a3c72ac3a2bf89b1f76706/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs:40:9:
Box<dyn Any>
stack backtrace:
   0:     0x773530f2e243 - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::h5d4004938ff2c5de
   1:     0x77353160277f - core::fmt::write::he40d39caeedce22d
   2:     0x773530f23e83 - std::io::Write::write_fmt::h6b481595dd1fc53f
   3:     0x773530f2e0a2 - std::sys::backtrace::BacktraceLock::print::h6122e56851fd7e04
   4:     0x773530f31b9a - std::panicking::default_hook::{{closure}}::h5da9a6ee005a6c0c
   5:     0x773530f3171f - std::panicking::default_hook::he77158b4319b132a
   6:     0x7735300095d3 - std[abb3b870cf4d8027]::panicking::update_hook::<alloc[3b9c56f51ca07bea]::boxed::Box<rustc_driver_impl[7eb6cf164257341f]::install_ice_hook::{closure#1}>>::{closure#0}
   7:     0x773530f323eb - std::panicking::rust_panic_with_hook::hbc48a4f07e431d11
   8:     0x773530043861 - std[abb3b870cf4d8027]::panicking::begin_panic::<rustc_errors[3b19c8b340e0e702]::ExplicitBug>::{closure#0}
   9:     0x773530037d86 - std[abb3b870cf4d8027]::sys::backtrace::__rust_end_short_backtrace::<std[abb3b870cf4d8027]::panicking::begin_panic<rustc_errors[3b19c8b340e0e702]::ExplicitBug>::{closure#0}, !>
  10:     0x773530037c17 - std[abb3b870cf4d8027]::panicking::begin_panic::<rustc_errors[3b19c8b340e0e702]::ExplicitBug>
  11:     0x77353004d341 - <rustc_errors[3b19c8b340e0e702]::diagnostic::BugAbort as rustc_errors[3b19c8b340e0e702]::diagnostic::EmissionGuarantee>::emit_producing_guarantee
  12:     0x77353061900a - rustc_middle[6ca7f7d3ce556234]::util::bug::opt_span_bug_fmt::<rustc_span[376a63540bfd47fc]::span_encoding::Span>::{closure#0}
  13:     0x7735305f8bea - rustc_middle[6ca7f7d3ce556234]::ty::context::tls::with_opt::<rustc_middle[6ca7f7d3ce556234]::util::bug::opt_span_bug_fmt<rustc_span[376a63540bfd47fc]::span_encoding::Span>::{closure#0}, !>::{closure#0}
  14:     0x7735305f8a5b - rustc_middle[6ca7f7d3ce556234]::ty::context::tls::with_context_opt::<rustc_middle[6ca7f7d3ce556234]::ty::context::tls::with_opt<rustc_middle[6ca7f7d3ce556234]::util::bug::opt_span_bug_fmt<rustc_span[376a63540bfd47fc]::span_encoding::Span>::{closure#0}, !>::{closure#0}, !>
  15:     0x77352d6a7e90 - rustc_middle[6ca7f7d3ce556234]::util::bug::bug_fmt
  16:     0x7735327519a9 - rustc_codegen_llvm[5e38973cde8d21c0]::base::compile_codegen_unit::module_codegen
  17:     0x773532714c4d - <rustc_codegen_llvm[5e38973cde8d21c0]::LlvmCodegenBackend as rustc_codegen_ssa[87a67ccac236a82e]::traits::backend::ExtraBackendMethods>::compile_codegen_unit
  18:     0x7735327129b3 - rustc_codegen_ssa[87a67ccac236a82e]::base::codegen_crate::<rustc_codegen_llvm[5e38973cde8d21c0]::LlvmCodegenBackend>
  19:     0x773532837083 - <rustc_codegen_llvm[5e38973cde8d21c0]::LlvmCodegenBackend as rustc_codegen_ssa[87a67ccac236a82e]::traits::backend::CodegenBackend>::codegen_crate
  20:     0x773532836732 - <rustc_interface[f681bac94ac292a9]::queries::Linker>::codegen_and_build_linker
  21:     0x77353282ca87 - rustc_interface[f681bac94ac292a9]::passes::create_and_enter_global_ctxt::<core[7243450d3d38063e]::option::Option<rustc_interface[f681bac94ac292a9]::queries::Linker>, rustc_driver_impl[7eb6cf164257341f]::run_compiler::{closure#0}::{closure#2}>::{closure#2}::{closure#0}
  22:     0x77353286756f - rustc_interface[f681bac94ac292a9]::interface::run_compiler::<(), rustc_driver_impl[7eb6cf164257341f]::run_compiler::{closure#0}>::{closure#1}
  23:     0x773532807e38 - std[abb3b870cf4d8027]::sys::backtrace::__rust_begin_short_backtrace::<rustc_interface[f681bac94ac292a9]::util::run_in_thread_with_globals<rustc_interface[f681bac94ac292a9]::util::run_in_thread_pool_with_globals<rustc_interface[f681bac94ac292a9]::interface::run_compiler<(), rustc_driver_impl[7eb6cf164257341f]::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>
  24:     0x773532807b16 - <<std[abb3b870cf4d8027]::thread::Builder>::spawn_unchecked_<rustc_interface[f681bac94ac292a9]::util::run_in_thread_with_globals<rustc_interface[f681bac94ac292a9]::util::run_in_thread_pool_with_globals<rustc_interface[f681bac94ac292a9]::interface::run_compiler<(), rustc_driver_impl[7eb6cf164257341f]::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}, ()>::{closure#1} as core[7243450d3d38063e]::ops::function::FnOnce<()>>::call_once::{shim:vtable#0}
  25:     0x77353280ddfd - std::sys::pal::unix::thread::Thread::new::thread_start::h277742a54d34f956
  26:     0x77352c2a57eb - <unknown>
  27:     0x77352c32918c - <unknown>
  28:                0x0 - <unknown>

note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md

note: please make sure that you have updated to the latest nightly

note: rustc 1.90.0-nightly (f26e58023 2025-06-30) running on x86_64-unknown-linux-gnu

note: compiler flags: -Z sanitizer=kcfi -C panic=abort -Z dump-mir-dir=dir

query stack during panic:
end of query stack
error: aborting due to 1 previous error; 5 warnings emitted


@rustbot label +F-abi_custom

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-control-flow-integrityArea: Control Flow Integrity (CFI) security mitigationA-nakedArea: `#[naked]`, prologue and epilogue-free, functions, https://git.io/vAzzSC-bugCategory: This is a bug.I-ICEIssue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️PG-exploit-mitigationsProject group: Exploit mitigationsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions