Skip to content

Commit 552fc2f

Browse files
authored
Errored when inline asm contans null bytes (#859)
1 parent 2205317 commit 552fc2f

File tree

6 files changed

+71
-5
lines changed

6 files changed

+71
-5
lines changed

src/asm.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ use rustc_codegen_ssa::traits::{
1212
};
1313
use rustc_middle::bug;
1414
use rustc_middle::ty::Instance;
15-
use rustc_span::Span;
15+
use rustc_span::{DUMMY_SP, Span};
1616
use rustc_target::asm::*;
1717

1818
use crate::builder::Builder;
1919
use crate::callee::get_fn;
2020
use crate::context::CodegenCx;
21-
use crate::errors::UnwindingInlineAsm;
21+
use crate::errors::{NulBytesInAsm, UnwindingInlineAsm};
2222
use crate::type_of::LayoutGccExt;
2323

2424
// Rust asm! and GCC Extended Asm semantics differ substantially.
@@ -530,8 +530,15 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
530530
template_str.push_str(INTEL_SYNTAX_INS);
531531
}
532532

533-
// 4. Generate Extended Asm block
533+
// NOTE: GCC's extended asm uses CString which cannot contain nul bytes.
534+
// Emit an error if there are any nul bytes in the template string.
535+
if template_str.contains('\0') {
536+
let err_sp = span.first().copied().unwrap_or(DUMMY_SP);
537+
self.sess().dcx().emit_err(NulBytesInAsm { span: err_sp });
538+
return;
539+
}
534540

541+
// 4. Generate Extended Asm block
535542
let block = self.llbb();
536543
let extended_asm = if let Some(dest) = dest {
537544
assert!(!labels.is_empty());
@@ -859,7 +866,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
859866
template: &[InlineAsmTemplatePiece],
860867
operands: &[GlobalAsmOperandRef<'tcx>],
861868
options: InlineAsmOptions,
862-
_line_spans: &[Span],
869+
line_spans: &[Span],
863870
) {
864871
let asm_arch = self.tcx.sess.asm_arch.unwrap();
865872

@@ -926,6 +933,13 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
926933
}
927934
// NOTE: seems like gcc will put the asm in the wrong section, so set it to .text manually.
928935
template_str.push_str("\n.popsection");
936+
// NOTE: GCC's add_top_level_asm uses CString which cannot contain nul bytes.
937+
// Emit an error if there are any nul bytes in the template string.
938+
if template_str.contains('\0') {
939+
let span = line_spans.first().copied().unwrap_or(DUMMY_SP);
940+
self.tcx.dcx().emit_err(NulBytesInAsm { span });
941+
return;
942+
}
929943
self.context.add_top_level_asm(None, &template_str);
930944
}
931945

src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,10 @@ pub(crate) struct LtoBitcodeFromRlib {
2323
#[derive(Diagnostic)]
2424
#[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")]
2525
pub(crate) struct ExplicitTailCallsUnsupported;
26+
27+
#[derive(Diagnostic)]
28+
#[diag("asm contains a NUL byte")]
29+
pub(crate) struct NulBytesInAsm {
30+
#[primary_span]
31+
pub span: Span,
32+
}

tests/compile/asm_nul_byte.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Compiler:
2+
// status: error
3+
// stderr:
4+
// error: asm contains a NUL byte
5+
// ...
6+
7+
// Test that inline asm containing a NUL byte emits an error.
8+
9+
use std::arch::asm;
10+
11+
fn main() {
12+
unsafe {
13+
asm!("\0");
14+
}
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Compiler:
2+
// status: error
3+
// stderr:
4+
// error: asm contains a NUL byte
5+
// ...
6+
7+
// Test that global_asm containing a NUL byte emits an error.
8+
9+
#![crate_type = "lib"]
10+
11+
use std::arch::global_asm;
12+
13+
global_asm!("\0");
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Compiler:
2+
// status: error
3+
// stderr:
4+
// ...
5+
// error: asm contains a NUL byte
6+
// ...
7+
8+
// Test that naked_asm containing a NUL byte emits an error.
9+
10+
#![crate_type = "lib"]
11+
12+
use std::arch::naked_asm;
13+
14+
#[unsafe(naked)]
15+
pub extern "C" fn nul_byte_naked() {
16+
naked_asm!("\0")
17+
}

tests/lang_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ fn compile_tests(tempdir: PathBuf, current_dir: String) {
201201
"lang compile",
202202
"tests/compile",
203203
TestMode::Compile,
204-
&["simd-ffi.rs"],
204+
&["simd-ffi.rs", "asm_nul_byte.rs", "global_asm_nul_byte.rs", "naked_asm_nul_byte.rs"],
205205
);
206206
}
207207

0 commit comments

Comments
 (0)