diff --git a/src/asm.rs b/src/asm.rs index 319f3d32787..a1445a0e63c 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::{NulBytesInAsm, UnwindingInlineAsm}; use crate::type_of::LayoutGccExt; // Rust asm! and GCC Extended Asm semantics differ substantially. @@ -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()); @@ -859,7 +866,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 +933,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 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(NulBytesInAsm { span }); + return; + } self.context.add_top_level_asm(None, &template_str); } diff --git a/src/errors.rs b/src/errors.rs index f5815e72339..de633d3bdde 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 NUL byte")] +pub(crate) struct NulBytesInAsm { + #[primary_span] + pub span: Span, +} 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") +} diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index 3f2cfde9a49..3d1d04661c8 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -201,7 +201,7 @@ 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"], ); }