Skip to content
/ rust Public
forked from rust-lang/rust

Commit edf787f

Browse files
authored
Rollup merge of rust-lang#159173 - chenyukang:yukang-fix-159015-no-mangle-eii, r=JonathanBrouwer
Add allowed list check on EII implementations attributes Fixes rust-lang#158293 Fixes rust-lang#159015 r? @bjorn3
2 parents e512d4c + 4e53ac1 commit edf787f

7 files changed

Lines changed: 226 additions & 29 deletions

File tree

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,48 @@ impl<'a> AstValidator<'a> {
12021202
self.visit_vis(vis);
12031203
self.visit_ident(ident);
12041204
}
1205+
1206+
// Check EII implementation attributes against an allowlist.
1207+
fn check_eii_impl_attrs(&self, attrs: &[Attribute], eii_impls: &[EiiImpl]) {
1208+
if eii_impls.is_empty() {
1209+
return;
1210+
}
1211+
1212+
let allowed_attrs: &[Symbol] = &[
1213+
sym::allow,
1214+
sym::warn,
1215+
sym::deny,
1216+
sym::forbid,
1217+
sym::expect,
1218+
sym::doc,
1219+
sym::inline,
1220+
sym::cold,
1221+
sym::optimize,
1222+
sym::coverage,
1223+
sym::sanitize,
1224+
sym::must_use,
1225+
sym::deprecated,
1226+
];
1227+
1228+
for attr in attrs {
1229+
let AttrKind::Normal(normal) = &attr.kind else {
1230+
continue;
1231+
};
1232+
if attr.has_any_name(allowed_attrs) {
1233+
continue;
1234+
}
1235+
1236+
let attr_name = pprust::path_to_string(&normal.item.path);
1237+
for eii_impl in eii_impls {
1238+
self.dcx().emit_err(diagnostics::EiiImplAttributeNotSupported {
1239+
attr_span: attr.span,
1240+
attr_name: &attr_name,
1241+
eii_span: eii_impl.span,
1242+
eii_name: pprust::path_to_string(&eii_impl.eii_macro_path),
1243+
});
1244+
}
1245+
}
1246+
}
12051247
}
12061248

12071249
/// Checks that generic parameters are in the correct order,
@@ -1391,6 +1433,7 @@ impl Visitor<'_> for AstValidator<'_> {
13911433
for EiiImpl { eii_macro_path, .. } in eii_impls {
13921434
self.visit_path(eii_macro_path);
13931435
}
1436+
self.check_eii_impl_attrs(&item.attrs, eii_impls);
13941437

13951438
let is_intrinsic = item.attrs.iter().any(|a| a.has_name(sym::rustc_intrinsic));
13961439
if body.is_none() && !is_intrinsic && !self.is_sdylib_interface {
@@ -1566,8 +1609,9 @@ impl Visitor<'_> for AstValidator<'_> {
15661609

15671610
visit::walk_item(self, item);
15681611
}
1569-
ItemKind::Static(StaticItem { expr, safety, .. }) => {
1612+
ItemKind::Static(StaticItem { expr, safety, eii_impls, .. }) => {
15701613
self.check_item_safety(item.span, *safety);
1614+
self.check_eii_impl_attrs(&item.attrs, eii_impls);
15711615
if matches!(safety, Safety::Unsafe(_)) {
15721616
self.dcx().emit_err(diagnostics::UnsafeStatic { span: item.span });
15731617
}

compiler/rustc_ast_passes/src/diagnostics.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,17 @@ pub(crate) struct FnParamForbiddenAttr {
189189
pub span: Span,
190190
}
191191

192+
#[derive(Diagnostic)]
193+
#[diag("`#[{$eii_name}]` is not allowed to have `#[{$attr_name}]`")]
194+
pub(crate) struct EiiImplAttributeNotSupported<'a> {
195+
#[primary_span]
196+
pub attr_span: Span,
197+
pub attr_name: &'a str,
198+
pub eii_name: String,
199+
#[label("`#[{$eii_name}]` is not allowed to have `#[{$attr_name}]`")]
200+
pub eii_span: Span,
201+
}
202+
192203
#[derive(Diagnostic)]
193204
#[diag("`self` parameter is only allowed in associated functions")]
194205
#[note("associated functions are those in `impl` or `trait` definitions")]

compiler/rustc_passes/src/check_attr.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -781,22 +781,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
781781
sig_span: sig.span,
782782
});
783783
}
784-
785-
if let Some(impls) = find_attr!(attrs, EiiImpls(impls) => impls) {
786-
let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
787-
for i in impls {
788-
let name = match i.resolution {
789-
EiiImplResolution::Macro(def_id) => self.tcx.item_name(def_id),
790-
EiiImplResolution::Known(def_id) => self.tcx.item_name(def_id),
791-
EiiImplResolution::Error(_eg) => continue,
792-
};
793-
self.dcx().emit_err(diagnostics::EiiWithTrackCaller {
794-
attr_span,
795-
name,
796-
sig_span: sig.span,
797-
});
798-
}
799-
}
800784
}
801785
_ => {}
802786
}

compiler/rustc_passes/src/diagnostics.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,16 +1082,6 @@ pub(crate) struct EiiImplRequiresUnsafeSuggestion {
10821082
pub right: Span,
10831083
}
10841084

1085-
#[derive(Diagnostic)]
1086-
#[diag("`#[{$name}]` is not allowed to have `#[track_caller]`")]
1087-
pub(crate) struct EiiWithTrackCaller {
1088-
#[primary_span]
1089-
pub attr_span: Span,
1090-
pub name: Symbol,
1091-
#[label("`#[{$name}]` is not allowed to have `#[track_caller]`")]
1092-
pub sig_span: Span,
1093-
}
1094-
10951085
#[derive(Diagnostic)]
10961086
#[diag("`#[{$name}]` {$kind} required, but not found")]
10971087
pub(crate) struct EiiWithoutImpl {
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// EII implementations only accept attributes from a conservative allowlist.
2+
// Regression test for #159015
3+
4+
//@ edition: 2024
5+
//@ needs-asm-support
6+
7+
#![feature(coverage_attribute)]
8+
#![feature(extern_item_impls)]
9+
#![feature(optimize_attribute)]
10+
#![feature(sanitize)]
11+
12+
#[eii]
13+
fn allowed();
14+
15+
/// Sugared and explicit documentation attributes are both allowed.
16+
#[allowed]
17+
#[allow(dead_code)]
18+
#[warn(unreachable_code)]
19+
#[deny(unused_mut)]
20+
#[forbid(unsafe_code)]
21+
#[expect(unused_variables)]
22+
#[cfg(all())]
23+
#[doc = "An allowed EII implementation."]
24+
#[cold]
25+
#[optimize(none)]
26+
#[coverage(off)]
27+
#[sanitize(address = "off")]
28+
#[must_use]
29+
#[deprecated]
30+
fn allowed_impl() {
31+
let unused = ();
32+
}
33+
34+
#[eii]
35+
fn allowed_inline();
36+
37+
#[allowed_inline]
38+
#[allow(unused_attributes)]
39+
#[cfg_attr(all(), inline)]
40+
fn allowed_inline_impl() {}
41+
42+
#[eii]
43+
fn foo();
44+
45+
#[foo]
46+
#[unsafe(no_mangle)]
47+
//~^ ERROR `#[foo]` is not allowed to have `#[no_mangle]`
48+
fn bar() {}
49+
50+
#[eii]
51+
fn baz();
52+
53+
#[baz]
54+
#[unsafe(export_name = "qux")]
55+
//~^ ERROR `#[baz]` is not allowed to have `#[export_name]`
56+
fn qux() {}
57+
58+
#[eii]
59+
fn quux();
60+
61+
#[quux]
62+
#[unsafe(link_section = "__TEXT,__text")]
63+
//~^ ERROR `#[quux]` is not allowed to have `#[link_section]`
64+
fn corge() {}
65+
66+
#[eii]
67+
fn grault();
68+
69+
#[grault]
70+
#[track_caller]
71+
//~^ ERROR `#[grault]` is not allowed to have `#[track_caller]`
72+
fn garply() {}
73+
74+
#[eii]
75+
extern "C" fn naked_attr();
76+
77+
#[naked_attr]
78+
#[unsafe(naked)]
79+
//~^ ERROR `#[naked_attr]` is not allowed to have `#[naked]`
80+
extern "C" fn naked_attr_impl() {
81+
core::arch::naked_asm!("")
82+
}
83+
84+
#[eii]
85+
fn multiple_invalid_attrs();
86+
87+
#[multiple_invalid_attrs]
88+
#[unsafe(no_mangle)]
89+
//~^ ERROR `#[multiple_invalid_attrs]` is not allowed to have `#[no_mangle]`
90+
#[track_caller]
91+
//~^ ERROR `#[multiple_invalid_attrs]` is not allowed to have `#[track_caller]`
92+
fn multiple_invalid_attrs_impl() {}
93+
94+
#[eii(static_eii)]
95+
static STATIC_EII: u8;
96+
97+
#[static_eii]
98+
#[used]
99+
//~^ ERROR `#[static_eii]` is not allowed to have `#[used]`
100+
static STATIC_EII_IMPL: u8 = 0;
101+
102+
fn main() {}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
error: `#[foo]` is not allowed to have `#[no_mangle]`
2+
--> $DIR/implementation-attribute-allowlist-issue-159015.rs:46:1
3+
|
4+
LL | #[foo]
5+
| ------ `#[foo]` is not allowed to have `#[no_mangle]`
6+
LL | #[unsafe(no_mangle)]
7+
| ^^^^^^^^^^^^^^^^^^^^
8+
9+
error: `#[baz]` is not allowed to have `#[export_name]`
10+
--> $DIR/implementation-attribute-allowlist-issue-159015.rs:54:1
11+
|
12+
LL | #[baz]
13+
| ------ `#[baz]` is not allowed to have `#[export_name]`
14+
LL | #[unsafe(export_name = "qux")]
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
17+
error: `#[quux]` is not allowed to have `#[link_section]`
18+
--> $DIR/implementation-attribute-allowlist-issue-159015.rs:62:1
19+
|
20+
LL | #[quux]
21+
| ------- `#[quux]` is not allowed to have `#[link_section]`
22+
LL | #[unsafe(link_section = "__TEXT,__text")]
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: `#[grault]` is not allowed to have `#[track_caller]`
26+
--> $DIR/implementation-attribute-allowlist-issue-159015.rs:70:1
27+
|
28+
LL | #[grault]
29+
| --------- `#[grault]` is not allowed to have `#[track_caller]`
30+
LL | #[track_caller]
31+
| ^^^^^^^^^^^^^^^
32+
33+
error: `#[naked_attr]` is not allowed to have `#[naked]`
34+
--> $DIR/implementation-attribute-allowlist-issue-159015.rs:78:1
35+
|
36+
LL | #[naked_attr]
37+
| ------------- `#[naked_attr]` is not allowed to have `#[naked]`
38+
LL | #[unsafe(naked)]
39+
| ^^^^^^^^^^^^^^^^
40+
41+
error: `#[multiple_invalid_attrs]` is not allowed to have `#[no_mangle]`
42+
--> $DIR/implementation-attribute-allowlist-issue-159015.rs:88:1
43+
|
44+
LL | #[multiple_invalid_attrs]
45+
| ------------------------- `#[multiple_invalid_attrs]` is not allowed to have `#[no_mangle]`
46+
LL | #[unsafe(no_mangle)]
47+
| ^^^^^^^^^^^^^^^^^^^^
48+
49+
error: `#[multiple_invalid_attrs]` is not allowed to have `#[track_caller]`
50+
--> $DIR/implementation-attribute-allowlist-issue-159015.rs:90:1
51+
|
52+
LL | #[multiple_invalid_attrs]
53+
| ------------------------- `#[multiple_invalid_attrs]` is not allowed to have `#[track_caller]`
54+
...
55+
LL | #[track_caller]
56+
| ^^^^^^^^^^^^^^^
57+
58+
error: `#[static_eii]` is not allowed to have `#[used]`
59+
--> $DIR/implementation-attribute-allowlist-issue-159015.rs:98:1
60+
|
61+
LL | #[static_eii]
62+
| ------------- `#[static_eii]` is not allowed to have `#[used]`
63+
LL | #[used]
64+
| ^^^^^^^
65+
66+
error: aborting due to 8 previous errors
67+

tests/ui/eii/track_caller_errors.stderr

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ error: `#[decl1]` is not allowed to have `#[track_caller]`
44
LL | #[track_caller]
55
| ^^^^^^^^^^^^^^^
66
LL | #[decl1]
7-
LL | fn impl1(x: u64) {
8-
| ---------------- `#[decl1]` is not allowed to have `#[track_caller]`
7+
| -------- `#[decl1]` is not allowed to have `#[track_caller]`
98

109
error: aborting due to 1 previous error
1110

0 commit comments

Comments
 (0)