Skip to content

Commit e7dc14e

Browse files
Rollup merge of #145670 - jdonszelmann:port-sanitize, r=lcnr
port `sanitize` attribute to the new parsing infrastructure
2 parents 95f8b91 + 1c03ae1 commit e7dc14e

File tree

12 files changed

+281
-191
lines changed

12 files changed

+281
-191
lines changed

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 107 additions & 6 deletions
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::*;
@@ -464,18 +464,119 @@ impl<S: Stage> CombineAttributeParser<S> for ForceTargetFeatureParser {
464464
was_forced: true,
465465
};
466466
const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]);
467+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
468+
Allow(Target::Fn),
469+
Allow(Target::Method(MethodKind::Inherent)),
470+
Allow(Target::Method(MethodKind::Trait { body: true })),
471+
Allow(Target::Method(MethodKind::TraitImpl)),
472+
]);
467473

468474
fn extend<'c>(
469475
cx: &'c mut AcceptContext<'_, '_, S>,
470476
args: &'c ArgParser<'_>,
471477
) -> impl IntoIterator<Item = Self::Item> + 'c {
472478
parse_tf_attribute(cx, args)
473479
}
480+
}
474481

475-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
476-
Allow(Target::Fn),
477-
Allow(Target::Method(MethodKind::Inherent)),
478-
Allow(Target::Method(MethodKind::Trait { body: true })),
479-
Allow(Target::Method(MethodKind::TraitImpl)),
482+
pub(crate) struct SanitizeParser;
483+
484+
impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
485+
const PATH: &[Symbol] = &[sym::sanitize];
486+
487+
// FIXME: still checked in check_attrs.rs
488+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
489+
490+
const TEMPLATE: AttributeTemplate = template!(List: &[
491+
r#"address = "on|off""#,
492+
r#"kernel_address = "on|off""#,
493+
r#"cfi = "on|off""#,
494+
r#"hwaddress = "on|off""#,
495+
r#"kcfi = "on|off""#,
496+
r#"memory = "on|off""#,
497+
r#"memtag = "on|off""#,
498+
r#"shadow_call_stack = "on|off""#,
499+
r#"thread = "on|off""#
480500
]);
501+
502+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
503+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
504+
505+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
506+
let Some(list) = args.list() else {
507+
cx.expected_list(cx.attr_span);
508+
return None;
509+
};
510+
511+
let mut on_set = SanitizerSet::empty();
512+
let mut off_set = SanitizerSet::empty();
513+
514+
for item in list.mixed() {
515+
let Some(item) = item.meta_item() else {
516+
cx.expected_name_value(item.span(), None);
517+
continue;
518+
};
519+
520+
let path = item.path().word_sym();
521+
let Some(value) = item.args().name_value() else {
522+
cx.expected_name_value(item.span(), path);
523+
continue;
524+
};
525+
526+
let mut apply = |s: SanitizerSet| {
527+
let is_on = match value.value_as_str() {
528+
Some(sym::on) => true,
529+
Some(sym::off) => false,
530+
Some(_) => {
531+
cx.expected_specific_argument_strings(
532+
value.value_span,
533+
&[sym::on, sym::off],
534+
);
535+
return;
536+
}
537+
None => {
538+
cx.expected_string_literal(value.value_span, Some(value.value_as_lit()));
539+
return;
540+
}
541+
};
542+
543+
if is_on {
544+
on_set |= s;
545+
} else {
546+
off_set |= s;
547+
}
548+
};
549+
550+
match path {
551+
Some(sym::address) | Some(sym::kernel_address) => {
552+
apply(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
553+
}
554+
Some(sym::cfi) => apply(SanitizerSet::CFI),
555+
Some(sym::kcfi) => apply(SanitizerSet::KCFI),
556+
Some(sym::memory) => apply(SanitizerSet::MEMORY),
557+
Some(sym::memtag) => apply(SanitizerSet::MEMTAG),
558+
Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
559+
Some(sym::thread) => apply(SanitizerSet::THREAD),
560+
Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS),
561+
_ => {
562+
cx.expected_specific_argument_strings(
563+
item.path().span(),
564+
&[
565+
sym::address,
566+
sym::cfi,
567+
sym::kcfi,
568+
sym::memory,
569+
sym::memtag,
570+
sym::shadow_call_stack,
571+
sym::thread,
572+
sym::hwaddress,
573+
],
574+
);
575+
continue;
576+
}
577+
}
578+
}
579+
580+
Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span })
581+
}
481582
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use crate::attributes::allow_unstable::{
2020
use crate::attributes::body::CoroutineParser;
2121
use crate::attributes::codegen_attrs::{
2222
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
23-
NoMangleParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
23+
NoMangleParser, OptimizeParser, SanitizeParser, TargetFeatureParser, TrackCallerParser,
24+
UsedParser,
2425
};
2526
use crate::attributes::confusables::ConfusablesParser;
2627
use crate::attributes::deprecation::DeprecationParser;
@@ -184,6 +185,7 @@ attribute_parsers!(
184185
Single<RustcLayoutScalarValidRangeEnd>,
185186
Single<RustcLayoutScalarValidRangeStart>,
186187
Single<RustcObjectLifetimeDefaultParser>,
188+
Single<SanitizeParser>,
187189
Single<ShouldPanicParser>,
188190
Single<SkipDuringMethodDispatchParser>,
189191
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
@@ -293,6 +293,9 @@ fn process_builtin_attrs(
293293
codegen_fn_attrs.linkage = linkage;
294294
}
295295
}
296+
AttributeKind::Sanitize { span, .. } => {
297+
interesting_spans.sanitize = Some(*span);
298+
}
296299
_ => {}
297300
}
298301
}
@@ -310,7 +313,6 @@ fn process_builtin_attrs(
310313
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
311314
}
312315
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
313-
sym::sanitize => interesting_spans.sanitize = Some(attr.span()),
314316
sym::instruction_set => {
315317
codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr)
316318
}
@@ -560,79 +562,9 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
560562
}
561563
}
562564

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

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

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)