Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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);
}

Expand Down
7 changes: 7 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
15 changes: 15 additions & 0 deletions tests/compile/asm_nul_byte.rs
Original file line number Diff line number Diff line change
@@ -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");
}
}
13 changes: 13 additions & 0 deletions tests/compile/global_asm_nul_byte.rs
Original file line number Diff line number Diff line change
@@ -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");
17 changes: 17 additions & 0 deletions tests/compile/naked_asm_nul_byte.rs
Original file line number Diff line number Diff line change
@@ -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")
}
2 changes: 1 addition & 1 deletion tests/lang_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
);
}

Expand Down