Skip to content

Commit edd6b4c

Browse files
committed
port attribute to the new parsing infrastructure
1 parent f5703d5 commit edd6b4c

File tree

12 files changed

+273
-186
lines changed

12 files changed

+273
-186
lines changed

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, UsedBy};
1+
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
22
use rustc_session::parse::feature_err;
33

44
use super::prelude::*;
@@ -440,3 +440,102 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
440440
Warn(Target::MacroDef),
441441
]);
442442
}
443+
444+
pub(crate) struct SanitizeParser;
445+
446+
impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
447+
const PATH: &[Symbol] = &[sym::sanitize];
448+
449+
// FIXME: still checked in check_attrs.rs
450+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
451+
452+
const TEMPLATE: AttributeTemplate = template!(List: &[
453+
r#"address = "on|off""#,
454+
r#"kernel_address = "on|off""#,
455+
r#"cfi = "on|off""#,
456+
r#"hwaddress = "on|off""#,
457+
r#"kcfi = "on|off""#,
458+
r#"memory = "on|off""#,
459+
r#"memtag = "on|off""#,
460+
r#"shadow_call_stack = "on|off""#,
461+
r#"thread = "on|off""#
462+
]);
463+
464+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
465+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
466+
467+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
468+
let Some(list) = args.list() else {
469+
cx.expected_list(cx.attr_span);
470+
return None;
471+
};
472+
473+
let mut on_set = SanitizerSet::empty();
474+
let mut off_set = SanitizerSet::empty();
475+
476+
for item in list.mixed() {
477+
let Some(item) = item.meta_item() else {
478+
cx.expected_name_value(item.span(), None);
479+
continue;
480+
};
481+
482+
let path = item.path().word_sym();
483+
let Some(value) = item.args().name_value() else {
484+
cx.expected_name_value(item.span(), path);
485+
continue;
486+
};
487+
488+
let mut apply = |s: SanitizerSet| {
489+
let is_on = match value.value_as_str() {
490+
Some(sym::on) => true,
491+
Some(sym::off) => false,
492+
Some(_) => {
493+
cx.expected_specific_argument_strings(value.value_span, vec!["on", "off"]);
494+
return;
495+
}
496+
None => {
497+
cx.expected_string_literal(value.value_span, Some(value.value_as_lit()));
498+
return;
499+
}
500+
};
501+
502+
if is_on {
503+
on_set |= s;
504+
} else {
505+
off_set |= s;
506+
}
507+
};
508+
509+
match path {
510+
Some(sym::address) | Some(sym::kernel_address) => {
511+
apply(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
512+
}
513+
Some(sym::cfi) => apply(SanitizerSet::CFI),
514+
Some(sym::kcfi) => apply(SanitizerSet::KCFI),
515+
Some(sym::memory) => apply(SanitizerSet::MEMORY),
516+
Some(sym::memtag) => apply(SanitizerSet::MEMTAG),
517+
Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
518+
Some(sym::thread) => apply(SanitizerSet::THREAD),
519+
Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS),
520+
_ => {
521+
cx.expected_specific_argument_strings(
522+
item.path().span(),
523+
vec![
524+
"address",
525+
"cfi",
526+
"kcfi",
527+
"memory",
528+
"memtag",
529+
"shadow_call_stack",
530+
"thread",
531+
"hwaddress",
532+
],
533+
);
534+
continue;
535+
}
536+
}
537+
}
538+
539+
Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span })
540+
}
541+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::attributes::allow_unstable::{
2020
use crate::attributes::body::CoroutineParser;
2121
use crate::attributes::codegen_attrs::{
2222
ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser,
23-
TargetFeatureParser, TrackCallerParser, UsedParser,
23+
SanitizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
2424
};
2525
use crate::attributes::confusables::ConfusablesParser;
2626
use crate::attributes::deprecation::DeprecationParser;
@@ -183,6 +183,7 @@ attribute_parsers!(
183183
Single<RustcLayoutScalarValidRangeEnd>,
184184
Single<RustcLayoutScalarValidRangeStart>,
185185
Single<RustcObjectLifetimeDefaultParser>,
186+
Single<SanitizeParser>,
186187
Single<ShouldPanicParser>,
187188
Single<SkipDuringMethodDispatchParser>,
188189
Single<TransparencyParser>,

compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,6 @@ codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphizati
171171
172172
codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
173173
174-
codegen_ssa_invalid_sanitize = invalid argument for `sanitize`
175-
.note = expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
176-
177174
codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
178175
179176
codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 15 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,9 @@ fn process_builtin_attrs(
292292
codegen_fn_attrs.linkage = linkage;
293293
}
294294
}
295+
AttributeKind::Sanitize { span, .. } => {
296+
interesting_spans.sanitize = Some(*span);
297+
}
295298
_ => {}
296299
}
297300
}
@@ -309,7 +312,6 @@ fn process_builtin_attrs(
309312
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
310313
}
311314
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
312-
sym::sanitize => interesting_spans.sanitize = Some(attr.span()),
313315
sym::instruction_set => {
314316
codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr)
315317
}
@@ -559,79 +561,9 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
559561
}
560562
}
561563

562-
/// For an attr that has the `sanitize` attribute, read the list of
563-
/// disabled sanitizers. `current_attr` holds the information about
564-
/// previously parsed attributes.
565-
fn parse_sanitize_attr(
566-
tcx: TyCtxt<'_>,
567-
attr: &Attribute,
568-
current_attr: SanitizerSet,
569-
) -> SanitizerSet {
570-
let mut result = current_attr;
571-
if let Some(list) = attr.meta_item_list() {
572-
for item in list.iter() {
573-
let MetaItemInner::MetaItem(set) = item else {
574-
tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
575-
break;
576-
};
577-
let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
578-
match segments.as_slice() {
579-
// Similar to clang, sanitize(address = ..) and
580-
// sanitize(kernel_address = ..) control both ASan and KASan
581-
// Source: https://reviews.llvm.org/D44981.
582-
[sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::off) => {
583-
result |= SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
584-
}
585-
[sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::on) => {
586-
result &= !SanitizerSet::ADDRESS;
587-
result &= !SanitizerSet::KERNELADDRESS;
588-
}
589-
[sym::cfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::CFI,
590-
[sym::cfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::CFI,
591-
[sym::kcfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::KCFI,
592-
[sym::kcfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::KCFI,
593-
[sym::memory] if set.value_str() == Some(sym::off) => {
594-
result |= SanitizerSet::MEMORY
595-
}
596-
[sym::memory] if set.value_str() == Some(sym::on) => {
597-
result &= !SanitizerSet::MEMORY
598-
}
599-
[sym::memtag] if set.value_str() == Some(sym::off) => {
600-
result |= SanitizerSet::MEMTAG
601-
}
602-
[sym::memtag] if set.value_str() == Some(sym::on) => {
603-
result &= !SanitizerSet::MEMTAG
604-
}
605-
[sym::shadow_call_stack] if set.value_str() == Some(sym::off) => {
606-
result |= SanitizerSet::SHADOWCALLSTACK
607-
}
608-
[sym::shadow_call_stack] if set.value_str() == Some(sym::on) => {
609-
result &= !SanitizerSet::SHADOWCALLSTACK
610-
}
611-
[sym::thread] if set.value_str() == Some(sym::off) => {
612-
result |= SanitizerSet::THREAD
613-
}
614-
[sym::thread] if set.value_str() == Some(sym::on) => {
615-
result &= !SanitizerSet::THREAD
616-
}
617-
[sym::hwaddress] if set.value_str() == Some(sym::off) => {
618-
result |= SanitizerSet::HWADDRESS
619-
}
620-
[sym::hwaddress] if set.value_str() == Some(sym::on) => {
621-
result &= !SanitizerSet::HWADDRESS
622-
}
623-
_ => {
624-
tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
625-
}
626-
}
627-
}
628-
}
629-
result
630-
}
631-
632564
fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
633565
// Backtrack to the crate root.
634-
let disabled = match tcx.opt_local_parent(did) {
566+
let mut disabled = match tcx.opt_local_parent(did) {
635567
// Check the parent (recursively).
636568
Some(parent) => tcx.disabled_sanitizers_for(parent),
637569
// We reached the crate root without seeing an attribute, so
@@ -640,8 +572,17 @@ fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
640572
};
641573

642574
// Check for a sanitize annotation directly on this def.
643-
if let Some(attr) = tcx.get_attr(did, sym::sanitize) {
644-
return parse_sanitize_attr(tcx, attr, disabled);
575+
if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set))
576+
{
577+
// the on set is the set of sanitizers explicitly enabled.
578+
// we mask those out since we want the set of disabled sanitizers here
579+
disabled &= !*on_set;
580+
// the off set is the set of sanitizers explicitly disabled.
581+
// we or those in here.
582+
disabled |= *off_set;
583+
// the on set and off set are distjoint since there's a third option: unset.
584+
// a node may not set the sanitizer setting in which case it inherits from parents.
585+
// the code above in this function does this backtracking
645586
}
646587
disabled
647588
}

compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,14 +1120,6 @@ impl IntoDiagArg for ExpectedPointerMutability {
11201120
}
11211121
}
11221122

1123-
#[derive(Diagnostic)]
1124-
#[diag(codegen_ssa_invalid_sanitize)]
1125-
#[note]
1126-
pub(crate) struct InvalidSanitize {
1127-
#[primary_span]
1128-
pub span: Span,
1129-
}
1130-
11311123
#[derive(Diagnostic)]
11321124
#[diag(codegen_ssa_target_feature_safe_trait)]
11331125
pub(crate) struct TargetFeatureSafeTrait {

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
1010
use rustc_span::def_id::DefId;
1111
use rustc_span::hygiene::Transparency;
1212
use rustc_span::{Ident, Span, Symbol};
13+
pub use rustc_target::spec::SanitizerSet;
1314
use thin_vec::ThinVec;
1415

1516
use crate::attrs::pretty_printing::PrintAttribute;
@@ -505,6 +506,12 @@ pub enum AttributeKind {
505506
/// Represents `#[rustc_object_lifetime_default]`.
506507
RustcObjectLifetimeDefault,
507508

509+
/// Represents `#[sanitize]`
510+
///
511+
/// the on set and off set are distjoint since there's a third option: unset.
512+
/// a node may not set the sanitizer setting in which case it inherits from parents.
513+
Sanitize { on_set: SanitizerSet, off_set: SanitizerSet, span: Span },
514+
508515
/// Represents `#[should_panic]`
509516
ShouldPanic { reason: Option<Symbol>, span: Span },
510517

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ impl AttributeKind {
7373
RustcLayoutScalarValidRangeEnd(..) => Yes,
7474
RustcLayoutScalarValidRangeStart(..) => Yes,
7575
RustcObjectLifetimeDefault => No,
76+
Sanitize { .. } => No,
7677
ShouldPanic { .. } => No,
7778
SkipDuringMethodDispatch { .. } => No,
7879
SpecializationTrait(..) => No,

compiler/rustc_hir/src/attrs/pretty_printing.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_ast::{AttrStyle, IntTy, UintTy};
66
use rustc_ast_pretty::pp::Printer;
77
use rustc_span::hygiene::Transparency;
88
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
9+
use rustc_target::spec::SanitizerSet;
910
use thin_vec::ThinVec;
1011

1112
/// This trait is used to print attributes in `rustc_hir_pretty`.
@@ -146,4 +147,14 @@ macro_rules! print_tup {
146147
print_tup!(A B C D E F G H);
147148
print_skip!(Span, (), ErrorGuaranteed);
148149
print_disp!(u16, bool, NonZero<u32>);
149-
print_debug!(Symbol, Ident, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
150+
print_debug!(
151+
Symbol,
152+
Ident,
153+
UintTy,
154+
IntTy,
155+
Align,
156+
AttrStyle,
157+
CommentKind,
158+
Transparency,
159+
SanitizerSet,
160+
);

0 commit comments

Comments
 (0)