From 593a71b29f7a089403345487538165891f711e28 Mon Sep 17 00:00:00 2001 From: Harin Date: Thu, 26 Feb 2026 22:56:23 +0530 Subject: [PATCH 1/5] Errored when inline asm contans null bytes --- src/asm.rs | 13 ++++++++++--- src/errors.rs | 7 +++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 319f3d32787..5e525ea3a7a 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -12,13 +12,13 @@ use rustc_codegen_ssa::traits::{ }; use rustc_middle::bug; use rustc_middle::ty::Instance; -use rustc_span::Span; +use rustc_span::{DUMMY_SP, Span}; use rustc_target::asm::*; use crate::builder::Builder; use crate::callee::get_fn; use crate::context::CodegenCx; -use crate::errors::UnwindingInlineAsm; +use crate::errors::{NullBytesInAsm, UnwindingInlineAsm}; use crate::type_of::LayoutGccExt; // Rust asm! and GCC Extended Asm semantics differ substantially. @@ -859,7 +859,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, - _line_spans: &[Span], + line_spans: &[Span], ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -926,6 +926,13 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } // NOTE: seems like gcc will put the asm in the wrong section, so set it to .text manually. template_str.push_str("\n.popsection"); + // NOTE: GCC's add_top_level_asm uses CString which cannot contain null bytes. + // Emit an error if there are any null bytes in the template string. + if template_str.contains('\0') { + let span = line_spans.first().copied().unwrap_or(DUMMY_SP); + self.tcx.dcx().emit_err(NullBytesInAsm { span }); + return; + } self.context.add_top_level_asm(None, &template_str); } diff --git a/src/errors.rs b/src/errors.rs index f5815e72339..fdbfeaf7d30 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -23,3 +23,10 @@ pub(crate) struct LtoBitcodeFromRlib { #[derive(Diagnostic)] #[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")] pub(crate) struct ExplicitTailCallsUnsupported; + +#[derive(Diagnostic)] +#[diag("asm contains a NULL byte")] +pub(crate) struct NullBytesInAsm { + #[primary_span] + pub span: Span, +} From a1f91b200d4b51461444ecd9939aeed926736eb4 Mon Sep 17 00:00:00 2001 From: Harin Date: Fri, 27 Feb 2026 22:04:24 +0530 Subject: [PATCH 2/5] corrected typo --- src/asm.rs | 8 ++++---- src/errors.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 5e525ea3a7a..81187677519 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -18,7 +18,7 @@ use rustc_target::asm::*; use crate::builder::Builder; use crate::callee::get_fn; use crate::context::CodegenCx; -use crate::errors::{NullBytesInAsm, UnwindingInlineAsm}; +use crate::errors::{NulBytesInAsm, UnwindingInlineAsm}; use crate::type_of::LayoutGccExt; // Rust asm! and GCC Extended Asm semantics differ substantially. @@ -926,11 +926,11 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } // NOTE: seems like gcc will put the asm in the wrong section, so set it to .text manually. template_str.push_str("\n.popsection"); - // NOTE: GCC's add_top_level_asm uses CString which cannot contain null bytes. - // Emit an error if there are any null bytes in the template string. + // NOTE: GCC's add_top_level_asm uses CString which cannot contain nul bytes. + // Emit an error if there are any nul bytes in the template string. if template_str.contains('\0') { let span = line_spans.first().copied().unwrap_or(DUMMY_SP); - self.tcx.dcx().emit_err(NullBytesInAsm { span }); + self.tcx.dcx().emit_err(NulBytesInAsm { span }); return; } self.context.add_top_level_asm(None, &template_str); diff --git a/src/errors.rs b/src/errors.rs index fdbfeaf7d30..de633d3bdde 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -25,8 +25,8 @@ pub(crate) struct LtoBitcodeFromRlib { pub(crate) struct ExplicitTailCallsUnsupported; #[derive(Diagnostic)] -#[diag("asm contains a NULL byte")] -pub(crate) struct NullBytesInAsm { +#[diag("asm contains a NUL byte")] +pub(crate) struct NulBytesInAsm { #[primary_span] pub span: Span, } From fb88fb2ed738a602575dca66e232e8e34453e699 Mon Sep 17 00:00:00 2001 From: Harin Date: Sun, 1 Mar 2026 16:32:45 +0530 Subject: [PATCH 3/5] Add NUL byte check for inline asm and tests for asm/global_asm/naked_asm --- src/asm.rs | 9 ++++++++- tests/compile/asm_nul_byte.rs | 15 +++++++++++++++ tests/compile/global_asm_nul_byte.rs | 13 +++++++++++++ tests/compile/naked_asm_nul_byte.rs | 17 +++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/compile/asm_nul_byte.rs create mode 100644 tests/compile/global_asm_nul_byte.rs create mode 100644 tests/compile/naked_asm_nul_byte.rs diff --git a/src/asm.rs b/src/asm.rs index 81187677519..a1445a0e63c 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -530,8 +530,15 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { template_str.push_str(INTEL_SYNTAX_INS); } - // 4. Generate Extended Asm block + // NOTE: GCC's extended asm uses CString which cannot contain nul bytes. + // Emit an error if there are any nul bytes in the template string. + if template_str.contains('\0') { + let err_sp = span.first().copied().unwrap_or(DUMMY_SP); + self.sess().dcx().emit_err(NulBytesInAsm { span: err_sp }); + return; + } + // 4. Generate Extended Asm block let block = self.llbb(); let extended_asm = if let Some(dest) = dest { assert!(!labels.is_empty()); diff --git a/tests/compile/asm_nul_byte.rs b/tests/compile/asm_nul_byte.rs new file mode 100644 index 00000000000..fd5a4f98aa2 --- /dev/null +++ b/tests/compile/asm_nul_byte.rs @@ -0,0 +1,15 @@ +// Compiler: +// status: error +// stderr: +// error: asm contains a NUL byte +// ... + +// Test that inline asm containing a NUL byte emits an error. + +use std::arch::asm; + +fn main() { + unsafe { + asm!("\0"); + } +} diff --git a/tests/compile/global_asm_nul_byte.rs b/tests/compile/global_asm_nul_byte.rs new file mode 100644 index 00000000000..12d647c733f --- /dev/null +++ b/tests/compile/global_asm_nul_byte.rs @@ -0,0 +1,13 @@ +// Compiler: +// status: error +// stderr: +// error: asm contains a NUL byte +// ... + +// Test that global_asm containing a NUL byte emits an error. + +#![crate_type = "lib"] + +use std::arch::global_asm; + +global_asm!("\0"); diff --git a/tests/compile/naked_asm_nul_byte.rs b/tests/compile/naked_asm_nul_byte.rs new file mode 100644 index 00000000000..85be3704a5e --- /dev/null +++ b/tests/compile/naked_asm_nul_byte.rs @@ -0,0 +1,17 @@ +// Compiler: +// status: error +// stderr: +// ... +// error: asm contains a NUL byte +// ... + +// Test that naked_asm containing a NUL byte emits an error. + +#![crate_type = "lib"] + +use std::arch::naked_asm; + +#[unsafe(naked)] +pub extern "C" fn nul_byte_naked() { + naked_asm!("\0") +} From 33b6a308e70cbfd9629219a544b30217a7466927 Mon Sep 17 00:00:00 2001 From: Harin Date: Sun, 1 Mar 2026 16:57:01 +0530 Subject: [PATCH 4/5] ignored asm test on m68k --- tests/lang_tests.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index 3f2cfde9a49..3e6a9c187d6 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -201,7 +201,12 @@ fn compile_tests(tempdir: PathBuf, current_dir: String) { "lang compile", "tests/compile", TestMode::Compile, - &["simd-ffi.rs"], + &[ + "simd-ffi.rs", + "asm_nul_byte.rs", + "global_asm_nul_byte.rs", + "naked_asm_nul_byte.rs", + ], ); } From 505413f8f981c742c5f1a8298592ae02986af81d Mon Sep 17 00:00:00 2001 From: Harin Date: Sun, 1 Mar 2026 16:59:49 +0530 Subject: [PATCH 5/5] ran cargo fmt --- tests/lang_tests.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index 3e6a9c187d6..3d1d04661c8 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -201,12 +201,7 @@ fn compile_tests(tempdir: PathBuf, current_dir: String) { "lang compile", "tests/compile", TestMode::Compile, - &[ - "simd-ffi.rs", - "asm_nul_byte.rs", - "global_asm_nul_byte.rs", - "naked_asm_nul_byte.rs", - ], + &["simd-ffi.rs", "asm_nul_byte.rs", "global_asm_nul_byte.rs", "naked_asm_nul_byte.rs"], ); }