Skip to content

Commit a6023f4

Browse files
authored
Unrolled build for #155817
Rollup merge of #155817 - folkertdev:link-name-null-empty, r=mejrs validate `#[link_name = "..."]` & `#[link(name = "...")]` parameters fixes #155776 fixes #155484 specifically, do not allow NULL bytes and the empty string in `#[link_name = "..."]` and `#[link(name = "...")]`. Like some of the others I think this formally needs to be looked at by T-lang because these errors would not show up if not linking. The LLVM erorr on `#[linke_name = "\0"]` is emitted here, it is not e.g. target-specific. https://github.com/llvm/llvm-project/blob/d593279c0b2891f0b0c8af3f70a1a0383b4ad1b5/llvm/lib/IR/Value.cpp#L336-L342 On `#[link(name = "")]` we already error today. A NULL byte in `#[link(name = "\0")]` is caught by the linker (https://godbolt.org/z/vnz9sYbPs), using `#[link_name = ""]` makes LLVM generate a name (https://godbolt.org/z/1hWEo4cxf) which is not useful and likely to cause linker errors. r? jdonszelmann
2 parents ce89c89 + c08b9ab commit a6023f4

6 files changed

Lines changed: 146 additions & 25 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/link_attrs.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::session_diagnostics::{
1717
AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic,
1818
ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier,
1919
InvalidMachoSection, InvalidMachoSectionReason, LinkFrameworkApple, LinkOrdinalOutOfRange,
20-
LinkRequiresName, MultipleModifiers, NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows,
20+
LinkRequiresName, MultipleModifiers, NullOnLinkName, NullOnLinkSection, RawDylibOnlyWindows,
2121
WholeArchiveNeedsStatic,
2222
};
2323

@@ -42,6 +42,19 @@ impl SingleAttributeParser for LinkNameParser {
4242
return None;
4343
};
4444

45+
if name.as_str().contains('\0') {
46+
// `#[link_name = ...]` will be converted to a null-terminated string,
47+
// so it may not contain any null characters.
48+
cx.emit_err(NullOnLinkName { span: nv.value_span });
49+
return None;
50+
}
51+
if name.is_empty() {
52+
// Otherwise LLVM will just make up a name and the linker will fail
53+
// to find an empty symbol name.
54+
cx.emit_err(EmptyLinkName { span: nv.value_span });
55+
return None;
56+
}
57+
4558
Some(LinkName { name, span: cx.attr_span })
4659
}
4760
}
@@ -218,7 +231,7 @@ impl CombineAttributeParser for LinkParser {
218231
if wasm_import_module.is_some() {
219232
(name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
220233
}
221-
let Some((name, name_span)) = name else {
234+
let Some((name, _name_span)) = name else {
222235
cx.emit_err(LinkRequiresName { span: cx.attr_span });
223236
return None;
224237
};
@@ -230,12 +243,6 @@ impl CombineAttributeParser for LinkParser {
230243
}
231244
}
232245

233-
if let Some(NativeLibKind::RawDylib { .. }) = kind
234-
&& name.as_str().contains('\0')
235-
{
236-
cx.emit_err(RawDylibNoNul { span: name_span });
237-
}
238-
239246
Some(LinkEntry {
240247
span: cx.attr_span,
241248
kind: kind.unwrap_or(NativeLibKind::Unspecified),
@@ -265,9 +272,13 @@ impl LinkParser {
265272
return false;
266273
};
267274

275+
if link_name.as_str().contains('\0') {
276+
cx.emit_err(NullOnLinkName { span: nv.value_span });
277+
}
268278
if link_name.is_empty() {
269279
cx.emit_err(EmptyLinkName { span: nv.value_span });
270280
}
281+
271282
*name = Some((link_name, nv.value_span));
272283
true
273284
}

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,13 @@ pub(crate) struct NullOnLinkSection {
410410
pub span: Span,
411411
}
412412

413+
#[derive(Diagnostic)]
414+
#[diag("link name may not contain null characters", code = E0648)]
415+
pub(crate) struct NullOnLinkName {
416+
#[primary_span]
417+
pub span: Span,
418+
}
419+
413420
#[derive(Diagnostic)]
414421
#[diag("`objc::class!` may not contain null characters")]
415422
pub(crate) struct NullOnObjcClass {
@@ -984,13 +991,6 @@ pub(crate) struct LinkRequiresName {
984991
pub span: Span,
985992
}
986993

987-
#[derive(Diagnostic)]
988-
#[diag("link name must not contain NUL characters if link kind is `raw-dylib`")]
989-
pub(crate) struct RawDylibNoNul {
990-
#[primary_span]
991-
pub span: Span,
992-
}
993-
994994
#[derive(Diagnostic)]
995995
#[diag("link kind `raw-dylib` is only supported on Windows targets", code = E0455)]
996996
pub(crate) struct RawDylibOnlyWindows {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#![crate_type = "lib"]
2+
3+
#[link(name = "")]
4+
//~^ ERROR link name must not be empty
5+
unsafe extern "C" {
6+
#[link_name = ""]
7+
//~^ ERROR link name must not be empty
8+
safe fn empty();
9+
}
10+
11+
#[link(name = " ")]
12+
unsafe extern "C" {
13+
#[link_name = " "]
14+
safe fn this_is_fine();
15+
}
16+
17+
#[export_name = " "]
18+
extern "C" fn bar() -> i32 {
19+
42
20+
}
21+
22+
#[link(name = "\0")]
23+
//~^ ERROR link name may not contain null characters
24+
unsafe extern "C" {}
25+
26+
#[link(name = "foo\0")]
27+
//~^ ERROR link name may not contain null characters
28+
unsafe extern "C" {}
29+
30+
#[link(name = "\0foo")]
31+
//~^ ERROR link name may not contain null characters
32+
unsafe extern "C" {}
33+
34+
#[link(name = "fo\0o")]
35+
//~^ ERROR link name may not contain null characters
36+
unsafe extern "C" {}
37+
38+
unsafe extern "C" {
39+
#[link_name = "\0"]
40+
//~^ ERROR link name may not contain null characters
41+
safe fn empty_null();
42+
43+
#[link_name = "foo\0"]
44+
//~^ ERROR link name may not contain null characters
45+
safe fn trailing_null();
46+
47+
#[link_name = "\0foo"]
48+
//~^ ERROR link name may not contain null characters
49+
safe fn leading_null();
50+
51+
#[link_name = "fo\0o"]
52+
//~^ ERROR link name may not contain null characters
53+
safe fn middle_null();
54+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
error[E0454]: link name must not be empty
2+
--> $DIR/invalid-link-name.rs:3:15
3+
|
4+
LL | #[link(name = "")]
5+
| ^^ empty link name
6+
7+
error[E0454]: link name must not be empty
8+
--> $DIR/invalid-link-name.rs:6:19
9+
|
10+
LL | #[link_name = ""]
11+
| ^^ empty link name
12+
13+
error[E0648]: link name may not contain null characters
14+
--> $DIR/invalid-link-name.rs:22:15
15+
|
16+
LL | #[link(name = "\0")]
17+
| ^^^^
18+
19+
error[E0648]: link name may not contain null characters
20+
--> $DIR/invalid-link-name.rs:26:15
21+
|
22+
LL | #[link(name = "foo\0")]
23+
| ^^^^^^^
24+
25+
error[E0648]: link name may not contain null characters
26+
--> $DIR/invalid-link-name.rs:30:15
27+
|
28+
LL | #[link(name = "\0foo")]
29+
| ^^^^^^^
30+
31+
error[E0648]: link name may not contain null characters
32+
--> $DIR/invalid-link-name.rs:34:15
33+
|
34+
LL | #[link(name = "fo\0o")]
35+
| ^^^^^^^
36+
37+
error[E0648]: link name may not contain null characters
38+
--> $DIR/invalid-link-name.rs:39:19
39+
|
40+
LL | #[link_name = "\0"]
41+
| ^^^^
42+
43+
error[E0648]: link name may not contain null characters
44+
--> $DIR/invalid-link-name.rs:43:19
45+
|
46+
LL | #[link_name = "foo\0"]
47+
| ^^^^^^^
48+
49+
error[E0648]: link name may not contain null characters
50+
--> $DIR/invalid-link-name.rs:47:19
51+
|
52+
LL | #[link_name = "\0foo"]
53+
| ^^^^^^^
54+
55+
error[E0648]: link name may not contain null characters
56+
--> $DIR/invalid-link-name.rs:51:19
57+
|
58+
LL | #[link_name = "fo\0o"]
59+
| ^^^^^^^
60+
61+
error: aborting due to 10 previous errors
62+
63+
Some errors have detailed explanations: E0454, E0648.
64+
For more information about an error, try `rustc --explain E0454`.

tests/ui/linkage-attr/raw-dylib/elf/malformed-link-name.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ unsafe extern "C" {
1111
pub safe fn exit_0(status: i32) -> !; //~ ERROR link name must be well-formed if link kind is `raw-dylib`
1212
#[link_name = "@GLIBC_2.2.5"]
1313
pub safe fn exit_1(status: i32) -> !; //~ ERROR link name must be well-formed if link kind is `raw-dylib`
14-
#[link_name = "ex\0it@GLIBC_2.2.5"]
15-
pub safe fn exit_2(status: i32) -> !; //~ ERROR link name must be well-formed if link kind is `raw-dylib`
1614
#[link_name = "exit@@GLIBC_2.2.5"]
17-
pub safe fn exit_3(status: i32) -> !; //~ ERROR link name must be well-formed if link kind is `raw-dylib`
15+
pub safe fn exit_2(status: i32) -> !; //~ ERROR link name must be well-formed if link kind is `raw-dylib`
1816
}
1917

2018
fn main() {}

tests/ui/linkage-attr/raw-dylib/elf/malformed-link-name.stderr

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,5 @@ error: link name must be well-formed if link kind is `raw-dylib`
1616
LL | pub safe fn exit_2(status: i32) -> !;
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818

19-
error: link name must be well-formed if link kind is `raw-dylib`
20-
--> $DIR/malformed-link-name.rs:17:5
21-
|
22-
LL | pub safe fn exit_3(status: i32) -> !;
23-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24-
25-
error: aborting due to 4 previous errors
19+
error: aborting due to 3 previous errors
2620

0 commit comments

Comments
 (0)