Skip to content

Disallow export_name starting with "llvm." #140837

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
3 changes: 3 additions & 0 deletions compiler/rustc_codegen_ssa/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ codegen_ssa_expected_one_argument = expected one argument

codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`

codegen_ssa_export_name_llvm_intrinsic = exported symbol name must not start with `llvm.`
.note = symbols starting with `llvm.` are reserved for LLVM intrinsics

codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified

codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error}
Expand Down
16 changes: 12 additions & 4 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,21 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER
}
sym::export_name => {
if let Some(s) = attr.value_str() {
if s.as_str().contains('\0') {
if let Some(exported_name) = attr.value_str() {
let value_span = attr.value_span().expect("attibute has value but not a span");
if exported_name.as_str().contains('\0') {
// `#[export_name = ...]` will be converted to a null-terminated string,
// so it may not contain any null characters.
tcx.dcx().emit_err(errors::NullOnExport { span: attr.span() });
tcx.dcx().emit_err(errors::NullOnExport { span: value_span });
}
codegen_fn_attrs.export_name = Some(s);
if exported_name.as_str().starts_with("llvm.") {
// Symbols starting with "llvm." are reserved by LLVM
// trying to define those would produce invalid IR.
// LLVM complain about those *if* we enable LLVM verification checks
// but we often don't enable them by default due to perf reasons.
tcx.dcx().emit_err(errors::ExportNameLLVMIntrinsic { span: value_span });
}
codegen_fn_attrs.export_name = Some(exported_name);
mixed_export_name_no_mangle_lint_state.track_export_name(attr.span());
}
}
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ pub(crate) struct NullOnExport {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(codegen_ssa_export_name_llvm_intrinsic)]
#[note]
pub(crate) struct ExportNameLLVMIntrinsic {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(codegen_ssa_unsupported_instruction_set, code = E0779)]
pub(crate) struct UnsuportedInstructionSet {
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1304,7 +1304,6 @@ impl<'a> DiagCtxtHandle<'a> {
self.create_almost_fatal(fatal).emit()
}

// FIXME: This method should be removed (every error should have an associated error code).
#[rustc_lint_diagnostics]
#[track_caller]
pub fn struct_err(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
Expand Down
18 changes: 18 additions & 0 deletions tests/ui/attributes/export_name-checks.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![crate_type = "lib"]

// rdtsc is an existing LLVM intrinsic
#[export_name = "llvm.x86.rdtsc"]
//~^ ERROR: exported symbol name must not start with `llvm.`
pub unsafe fn foo(a: u8) -> u8 {
2 * a
}

// qwerty is not a real llvm intrinsic
#[export_name = "llvm.x86.qwerty"]
//~^ ERROR: exported symbol name must not start with `llvm.`
pub unsafe fn bar(a: u8) -> u8 {
2 * a
}

#[export_name="ab\0cd"] //~ ERROR `export_name` may not contain null characters
pub fn qux() {}
25 changes: 25 additions & 0 deletions tests/ui/attributes/export_name-checks.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error: exported symbol name must not start with `llvm.`
--> $DIR/export_name-checks.rs:4:17
|
LL | #[export_name = "llvm.x86.rdtsc"]
| ^^^^^^^^^^^^^^^^
|
= note: symbols starting with `llvm.` are reserved for LLVM intrinsics

error: exported symbol name must not start with `llvm.`
--> $DIR/export_name-checks.rs:11:17
|
LL | #[export_name = "llvm.x86.qwerty"]
| ^^^^^^^^^^^^^^^^^
|
= note: symbols starting with `llvm.` are reserved for LLVM intrinsics

error[E0648]: `export_name` may not contain null characters
--> $DIR/export_name-checks.rs:17:15
|
LL | #[export_name="ab\0cd"]
| ^^^^^^^^

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0648`.
4 changes: 2 additions & 2 deletions tests/ui/error-codes/E0648.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0648]: `export_name` may not contain null characters
--> $DIR/E0648.rs:1:1
--> $DIR/E0648.rs:1:15
|
LL | #[export_name="\0foo"]
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^

error: aborting due to 1 previous error

Expand Down
Loading