Skip to content

Commit 35e0a3f

Browse files
committed
error on invalid macho section specifier
1 parent 1fe72d3 commit 35e0a3f

6 files changed

Lines changed: 157 additions & 3 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/link_attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
497497
return None;
498498
}
499499

500-
Some(LinkSection { name, span: cx.attr_span })
500+
Some(LinkSection { name, name_span: nv.value_span, span: cx.attr_span })
501501
}
502502
}
503503

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1229,8 +1229,9 @@ pub enum AttributeKind {
12291229

12301230
/// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
12311231
LinkSection {
1232-
name: Symbol,
12331232
span: Span,
1233+
name: Symbol,
1234+
name_span: Span,
12341235
},
12351236

12361237
/// Represents `#[linkage]`.

compiler/rustc_passes/src/check_attr.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ use rustc_session::lint::builtin::{
4343
use rustc_session::parse::feature_err;
4444
use rustc_span::edition::Edition;
4545
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
46+
use rustc_target::spec::BinaryFormat;
4647
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
4748
use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
4849
use rustc_trait_selection::traits::ObligationCtxt;
@@ -199,6 +200,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
199200
Attribute::Parsed(AttributeKind::Link(_, attr_span)) => {
200201
self.check_link(hir_id, *attr_span, span, target)
201202
},
203+
Attribute::Parsed(AttributeKind::LinkSection { span: _, name, name_span }) => {
204+
self.check_link_section(*name, *name_span)
205+
},
202206
Attribute::Parsed(AttributeKind::MacroExport { span, .. }) => {
203207
self.check_macro_export(hir_id, *span, target)
204208
},
@@ -249,7 +253,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
249253
| AttributeKind::Lang(..)
250254
| AttributeKind::LinkName { .. }
251255
| AttributeKind::LinkOrdinal { .. }
252-
| AttributeKind::LinkSection { .. }
253256
| AttributeKind::Linkage(..)
254257
| AttributeKind::MacroEscape( .. )
255258
| AttributeKind::MacroUse { .. }
@@ -1196,6 +1199,46 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
11961199
);
11971200
}
11981201

1202+
/// Checks if `#[link_section]` has a valid argument.
1203+
fn check_link_section(&self, name: Symbol, name_span: Span) {
1204+
// We (currently) only validate macho section specifiers.
1205+
match self.tcx.sess.target.binary_format {
1206+
BinaryFormat::MachO => match Self::check_link_section_macho(name) {
1207+
Ok(()) => {}
1208+
Err(reason) => {
1209+
let err = errors::InvalidMachoSection { name_span, reason };
1210+
self.tcx.dcx().emit_err(err);
1211+
}
1212+
},
1213+
BinaryFormat::Coff | BinaryFormat::Elf | BinaryFormat::Wasm | BinaryFormat::Xcoff => {}
1214+
}
1215+
}
1216+
1217+
fn check_link_section_macho(name: Symbol) -> Result<(), errors::InvalidMachoSectionReason> {
1218+
use errors::InvalidMachoSectionReason as Reason;
1219+
1220+
let mut parts = name.as_str().split(',').map(|s| s.trim());
1221+
1222+
// The segment can be empty.
1223+
let _segment = parts.next();
1224+
1225+
// But the section is required.
1226+
let section = match parts.next() {
1227+
None | Some("") => return Err(Reason::MissingSection),
1228+
Some(section) => section,
1229+
};
1230+
1231+
if section.len() > 16 {
1232+
return Err(Reason::SectionTooLong { section: section.to_string() });
1233+
}
1234+
1235+
// LLVM also checks the other components of the section specifier, but that logic is hard to
1236+
// keep in sync. We skip it here for now, assuming that if you got that far you'll be able
1237+
// to interpret the LLVM errors.
1238+
1239+
Ok(())
1240+
}
1241+
11991242
/// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
12001243
fn check_rustc_legacy_const_generics(
12011244
&self,

compiler/rustc_passes/src/errors.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,3 +1332,22 @@ pub(crate) struct UnknownFormatParameterForOnUnimplementedAttr {
13321332
pub(crate) struct OnMoveMalformedFormatLiterals {
13331333
pub name: Symbol,
13341334
}
1335+
1336+
#[derive(Diagnostic)]
1337+
#[diag("invalid macho section specifier")]
1338+
pub(crate) struct InvalidMachoSection {
1339+
#[primary_span]
1340+
#[label("not a valid macho section specifier")]
1341+
pub name_span: Span,
1342+
#[subdiagnostic]
1343+
pub reason: InvalidMachoSectionReason,
1344+
}
1345+
1346+
#[derive(Subdiagnostic)]
1347+
pub(crate) enum InvalidMachoSectionReason {
1348+
#[note("a macho section specifier requires a segment and a section, separated by a comma")]
1349+
#[help("an example of a valid macho section specifier is `__TEXT,__cstring`")]
1350+
MissingSection,
1351+
#[note("section name `{$section}` is longer than 16 bytes")]
1352+
SectionTooLong { section: String },
1353+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//@ add-minicore
2+
//@ compile-flags: --target aarch64-apple-darwin
3+
//@ needs-llvm-components: aarch64
4+
//@ ignore-backends: gcc
5+
#![feature(no_core, rustc_attrs, lang_items)]
6+
#![no_core]
7+
#![crate_type = "lib"]
8+
9+
extern crate minicore;
10+
use minicore::*;
11+
12+
#[unsafe(link_section = "foo")]
13+
//~^ ERROR invalid macho section specifier
14+
#[unsafe(no_mangle)]
15+
fn missing_section() {}
16+
17+
#[unsafe(link_section = "foo,")]
18+
//~^ ERROR invalid macho section specifier
19+
#[unsafe(no_mangle)]
20+
fn empty_section() {}
21+
22+
#[unsafe(link_section = "foo, ")]
23+
//~^ ERROR invalid macho section specifier
24+
#[unsafe(no_mangle)]
25+
fn whitespace_section() {}
26+
27+
#[unsafe(link_section = "foo,somelongwindedthing")]
28+
//~^ ERROR invalid macho section specifier
29+
#[unsafe(no_mangle)]
30+
fn section_too_long() {}
31+
32+
#[unsafe(link_section = "foo,bar")]
33+
#[unsafe(no_mangle)]
34+
fn segment_and_section() {}
35+
36+
#[unsafe(link_section = "foo,bar,")]
37+
#[unsafe(no_mangle)]
38+
fn segment_and_section_and_comma() {}
39+
40+
#[unsafe(link_section = ",foo")]
41+
#[unsafe(no_mangle)]
42+
fn missing_segment_is_fine() {}
43+
44+
#[unsafe(link_section = "__TEXT,__stubs,symbol_stubs,none,16")]
45+
#[unsafe(no_mangle)]
46+
fn stub_size_decimal() {}
47+
48+
#[unsafe(link_section = "__TEXT,__stubs,symbol_stubs,none,0x10")]
49+
#[unsafe(no_mangle)]
50+
fn stub_size_hex() {}
51+
52+
#[unsafe(link_section = "__TEXT,__stubs,symbol_stubs,none,020")]
53+
#[unsafe(no_mangle)]
54+
fn stub_size_oct() {}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error: invalid macho section specifier
2+
--> $DIR/link-section-macho.rs:12:25
3+
|
4+
LL | #[unsafe(link_section = "foo")]
5+
| ^^^^^ not a valid macho section specifier
6+
|
7+
= note: a macho section specifier requires a segment and a section, separated by a comma
8+
= help: an example of a valid macho section specifier is `__TEXT,__cstring`
9+
10+
error: invalid macho section specifier
11+
--> $DIR/link-section-macho.rs:17:25
12+
|
13+
LL | #[unsafe(link_section = "foo,")]
14+
| ^^^^^^ not a valid macho section specifier
15+
|
16+
= note: a macho section specifier requires a segment and a section, separated by a comma
17+
= help: an example of a valid macho section specifier is `__TEXT,__cstring`
18+
19+
error: invalid macho section specifier
20+
--> $DIR/link-section-macho.rs:22:25
21+
|
22+
LL | #[unsafe(link_section = "foo, ")]
23+
| ^^^^^^^ not a valid macho section specifier
24+
|
25+
= note: a macho section specifier requires a segment and a section, separated by a comma
26+
= help: an example of a valid macho section specifier is `__TEXT,__cstring`
27+
28+
error: invalid macho section specifier
29+
--> $DIR/link-section-macho.rs:27:25
30+
|
31+
LL | #[unsafe(link_section = "foo,somelongwindedthing")]
32+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not a valid macho section specifier
33+
|
34+
= note: section name `somelongwindedthing` is longer than 16 bytes
35+
36+
error: aborting due to 4 previous errors
37+

0 commit comments

Comments
 (0)