Skip to content

Commit 2ffa233

Browse files
committed
validate link name parameter
specifically, do not allow NULL bytes and the empty string
1 parent 68ffae4 commit 2ffa233

6 files changed

Lines changed: 146 additions & 12 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/link_attrs.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ 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,
21-
WholeArchiveNeedsStatic,
20+
LinkRequiresName, MultipleModifiers, NullOnLinkName, NullOnLinkSection, RawDylibNoNul,
21+
RawDylibOnlyWindows, WholeArchiveNeedsStatic,
2222
};
2323

2424
pub(crate) struct LinkNameParser;
@@ -46,6 +46,19 @@ impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
4646
return None;
4747
};
4848

49+
if name.as_str().contains('\0') {
50+
// `#[link_name = ...]` will be converted to a null-terminated string,
51+
// so it may not contain any null characters.
52+
cx.emit_err(NullOnLinkName { span: nv.value_span });
53+
return None;
54+
}
55+
if name.is_empty() {
56+
// Otherwise LLVM will just make up a name and the linker will fail
57+
// to find an empty symbol name.
58+
cx.emit_err(EmptyLinkName { span: nv.value_span });
59+
return None;
60+
}
61+
4962
Some(LinkName { name, span: cx.attr_span })
5063
}
5164
}
@@ -270,9 +283,13 @@ impl LinkParser {
270283
return false;
271284
};
272285

286+
if link_name.as_str().contains('\0') {
287+
cx.emit_err(NullOnLinkName { span: nv.value_span });
288+
}
273289
if link_name.is_empty() {
274290
cx.emit_err(EmptyLinkName { span: nv.value_span });
275291
}
292+
276293
*name = Some((link_name, nv.value_span));
277294
true
278295
}

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 7 additions & 0 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 {
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)