port attribute to the new parsing infrastructure
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, UsedBy};
|
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
|
|
||||||
use super::prelude::*;
|
use super::prelude::*;
|
||||||
@@ -464,6 +464,12 @@ impl<S: Stage> CombineAttributeParser<S> for ForceTargetFeatureParser {
|
|||||||
was_forced: true,
|
was_forced: true,
|
||||||
};
|
};
|
||||||
const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]);
|
const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]);
|
||||||
|
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||||
|
Allow(Target::Fn),
|
||||||
|
Allow(Target::Method(MethodKind::Inherent)),
|
||||||
|
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||||
|
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||||
|
]);
|
||||||
|
|
||||||
fn extend<'c>(
|
fn extend<'c>(
|
||||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||||
@@ -471,11 +477,106 @@ impl<S: Stage> CombineAttributeParser<S> for ForceTargetFeatureParser {
|
|||||||
) -> impl IntoIterator<Item = Self::Item> + 'c {
|
) -> impl IntoIterator<Item = Self::Item> + 'c {
|
||||||
parse_tf_attribute(cx, args)
|
parse_tf_attribute(cx, args)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
|
||||||
Allow(Target::Fn),
|
pub(crate) struct SanitizeParser;
|
||||||
Allow(Target::Method(MethodKind::Inherent)),
|
|
||||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
|
||||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
const PATH: &[Symbol] = &[sym::sanitize];
|
||||||
]);
|
|
||||||
|
// FIXME: still checked in check_attrs.rs
|
||||||
|
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
|
||||||
|
|
||||||
|
const TEMPLATE: AttributeTemplate = template!(List: &[
|
||||||
|
r#"address = "on|off""#,
|
||||||
|
r#"kernel_address = "on|off""#,
|
||||||
|
r#"cfi = "on|off""#,
|
||||||
|
r#"hwaddress = "on|off""#,
|
||||||
|
r#"kcfi = "on|off""#,
|
||||||
|
r#"memory = "on|off""#,
|
||||||
|
r#"memtag = "on|off""#,
|
||||||
|
r#"shadow_call_stack = "on|off""#,
|
||||||
|
r#"thread = "on|off""#
|
||||||
|
]);
|
||||||
|
|
||||||
|
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||||
|
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||||
|
|
||||||
|
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||||
|
let Some(list) = args.list() else {
|
||||||
|
cx.expected_list(cx.attr_span);
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut on_set = SanitizerSet::empty();
|
||||||
|
let mut off_set = SanitizerSet::empty();
|
||||||
|
|
||||||
|
for item in list.mixed() {
|
||||||
|
let Some(item) = item.meta_item() else {
|
||||||
|
cx.expected_name_value(item.span(), None);
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let path = item.path().word_sym();
|
||||||
|
let Some(value) = item.args().name_value() else {
|
||||||
|
cx.expected_name_value(item.span(), path);
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut apply = |s: SanitizerSet| {
|
||||||
|
let is_on = match value.value_as_str() {
|
||||||
|
Some(sym::on) => true,
|
||||||
|
Some(sym::off) => false,
|
||||||
|
Some(_) => {
|
||||||
|
cx.expected_specific_argument_strings(
|
||||||
|
value.value_span,
|
||||||
|
&[sym::on, sym::off],
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
cx.expected_string_literal(value.value_span, Some(value.value_as_lit()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_on {
|
||||||
|
on_set |= s;
|
||||||
|
} else {
|
||||||
|
off_set |= s;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match path {
|
||||||
|
Some(sym::address) | Some(sym::kernel_address) => {
|
||||||
|
apply(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
|
||||||
|
}
|
||||||
|
Some(sym::cfi) => apply(SanitizerSet::CFI),
|
||||||
|
Some(sym::kcfi) => apply(SanitizerSet::KCFI),
|
||||||
|
Some(sym::memory) => apply(SanitizerSet::MEMORY),
|
||||||
|
Some(sym::memtag) => apply(SanitizerSet::MEMTAG),
|
||||||
|
Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
|
||||||
|
Some(sym::thread) => apply(SanitizerSet::THREAD),
|
||||||
|
Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS),
|
||||||
|
_ => {
|
||||||
|
cx.expected_specific_argument_strings(
|
||||||
|
item.path().span(),
|
||||||
|
&[
|
||||||
|
sym::address,
|
||||||
|
sym::cfi,
|
||||||
|
sym::kcfi,
|
||||||
|
sym::memory,
|
||||||
|
sym::memtag,
|
||||||
|
sym::shadow_call_stack,
|
||||||
|
sym::thread,
|
||||||
|
sym::hwaddress,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ use crate::attributes::allow_unstable::{
|
|||||||
use crate::attributes::body::CoroutineParser;
|
use crate::attributes::body::CoroutineParser;
|
||||||
use crate::attributes::codegen_attrs::{
|
use crate::attributes::codegen_attrs::{
|
||||||
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
|
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
|
||||||
NoMangleParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
|
NoMangleParser, OptimizeParser, SanitizeParser, TargetFeatureParser, TrackCallerParser,
|
||||||
|
UsedParser,
|
||||||
};
|
};
|
||||||
use crate::attributes::confusables::ConfusablesParser;
|
use crate::attributes::confusables::ConfusablesParser;
|
||||||
use crate::attributes::deprecation::DeprecationParser;
|
use crate::attributes::deprecation::DeprecationParser;
|
||||||
@@ -184,6 +185,7 @@ attribute_parsers!(
|
|||||||
Single<RustcLayoutScalarValidRangeEnd>,
|
Single<RustcLayoutScalarValidRangeEnd>,
|
||||||
Single<RustcLayoutScalarValidRangeStart>,
|
Single<RustcLayoutScalarValidRangeStart>,
|
||||||
Single<RustcObjectLifetimeDefaultParser>,
|
Single<RustcObjectLifetimeDefaultParser>,
|
||||||
|
Single<SanitizeParser>,
|
||||||
Single<ShouldPanicParser>,
|
Single<ShouldPanicParser>,
|
||||||
Single<SkipDuringMethodDispatchParser>,
|
Single<SkipDuringMethodDispatchParser>,
|
||||||
Single<TransparencyParser>,
|
Single<TransparencyParser>,
|
||||||
|
|||||||
@@ -171,9 +171,6 @@ codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphizati
|
|||||||
|
|
||||||
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}`
|
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}`
|
||||||
|
|
||||||
codegen_ssa_invalid_sanitize = invalid argument for `sanitize`
|
|
||||||
.note = expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
|
|
||||||
|
|
||||||
codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
|
codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
|
||||||
|
|
||||||
codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
|
codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
|
||||||
|
|||||||
@@ -293,6 +293,9 @@ fn process_builtin_attrs(
|
|||||||
codegen_fn_attrs.linkage = linkage;
|
codegen_fn_attrs.linkage = linkage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AttributeKind::Sanitize { span, .. } => {
|
||||||
|
interesting_spans.sanitize = Some(*span);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,7 +313,6 @@ fn process_builtin_attrs(
|
|||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
|
||||||
}
|
}
|
||||||
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
|
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
|
||||||
sym::sanitize => interesting_spans.sanitize = Some(attr.span()),
|
|
||||||
sym::instruction_set => {
|
sym::instruction_set => {
|
||||||
codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr)
|
codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr)
|
||||||
}
|
}
|
||||||
@@ -560,79 +562,9 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For an attr that has the `sanitize` attribute, read the list of
|
|
||||||
/// disabled sanitizers. `current_attr` holds the information about
|
|
||||||
/// previously parsed attributes.
|
|
||||||
fn parse_sanitize_attr(
|
|
||||||
tcx: TyCtxt<'_>,
|
|
||||||
attr: &Attribute,
|
|
||||||
current_attr: SanitizerSet,
|
|
||||||
) -> SanitizerSet {
|
|
||||||
let mut result = current_attr;
|
|
||||||
if let Some(list) = attr.meta_item_list() {
|
|
||||||
for item in list.iter() {
|
|
||||||
let MetaItemInner::MetaItem(set) = item else {
|
|
||||||
tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
|
|
||||||
match segments.as_slice() {
|
|
||||||
// Similar to clang, sanitize(address = ..) and
|
|
||||||
// sanitize(kernel_address = ..) control both ASan and KASan
|
|
||||||
// Source: https://reviews.llvm.org/D44981.
|
|
||||||
[sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::off) => {
|
|
||||||
result |= SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
|
|
||||||
}
|
|
||||||
[sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::on) => {
|
|
||||||
result &= !SanitizerSet::ADDRESS;
|
|
||||||
result &= !SanitizerSet::KERNELADDRESS;
|
|
||||||
}
|
|
||||||
[sym::cfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::CFI,
|
|
||||||
[sym::cfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::CFI,
|
|
||||||
[sym::kcfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::KCFI,
|
|
||||||
[sym::kcfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::KCFI,
|
|
||||||
[sym::memory] if set.value_str() == Some(sym::off) => {
|
|
||||||
result |= SanitizerSet::MEMORY
|
|
||||||
}
|
|
||||||
[sym::memory] if set.value_str() == Some(sym::on) => {
|
|
||||||
result &= !SanitizerSet::MEMORY
|
|
||||||
}
|
|
||||||
[sym::memtag] if set.value_str() == Some(sym::off) => {
|
|
||||||
result |= SanitizerSet::MEMTAG
|
|
||||||
}
|
|
||||||
[sym::memtag] if set.value_str() == Some(sym::on) => {
|
|
||||||
result &= !SanitizerSet::MEMTAG
|
|
||||||
}
|
|
||||||
[sym::shadow_call_stack] if set.value_str() == Some(sym::off) => {
|
|
||||||
result |= SanitizerSet::SHADOWCALLSTACK
|
|
||||||
}
|
|
||||||
[sym::shadow_call_stack] if set.value_str() == Some(sym::on) => {
|
|
||||||
result &= !SanitizerSet::SHADOWCALLSTACK
|
|
||||||
}
|
|
||||||
[sym::thread] if set.value_str() == Some(sym::off) => {
|
|
||||||
result |= SanitizerSet::THREAD
|
|
||||||
}
|
|
||||||
[sym::thread] if set.value_str() == Some(sym::on) => {
|
|
||||||
result &= !SanitizerSet::THREAD
|
|
||||||
}
|
|
||||||
[sym::hwaddress] if set.value_str() == Some(sym::off) => {
|
|
||||||
result |= SanitizerSet::HWADDRESS
|
|
||||||
}
|
|
||||||
[sym::hwaddress] if set.value_str() == Some(sym::on) => {
|
|
||||||
result &= !SanitizerSet::HWADDRESS
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
|
fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
|
||||||
// Backtrack to the crate root.
|
// Backtrack to the crate root.
|
||||||
let disabled = match tcx.opt_local_parent(did) {
|
let mut disabled = match tcx.opt_local_parent(did) {
|
||||||
// Check the parent (recursively).
|
// Check the parent (recursively).
|
||||||
Some(parent) => tcx.disabled_sanitizers_for(parent),
|
Some(parent) => tcx.disabled_sanitizers_for(parent),
|
||||||
// We reached the crate root without seeing an attribute, so
|
// We reached the crate root without seeing an attribute, so
|
||||||
@@ -641,8 +573,17 @@ fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Check for a sanitize annotation directly on this def.
|
// Check for a sanitize annotation directly on this def.
|
||||||
if let Some(attr) = tcx.get_attr(did, sym::sanitize) {
|
if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set))
|
||||||
return parse_sanitize_attr(tcx, attr, disabled);
|
{
|
||||||
|
// the on set is the set of sanitizers explicitly enabled.
|
||||||
|
// we mask those out since we want the set of disabled sanitizers here
|
||||||
|
disabled &= !*on_set;
|
||||||
|
// the off set is the set of sanitizers explicitly disabled.
|
||||||
|
// we or those in here.
|
||||||
|
disabled |= *off_set;
|
||||||
|
// the on set and off set are distjoint since there's a third option: unset.
|
||||||
|
// a node may not set the sanitizer setting in which case it inherits from parents.
|
||||||
|
// the code above in this function does this backtracking
|
||||||
}
|
}
|
||||||
disabled
|
disabled
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1120,14 +1120,6 @@ impl IntoDiagArg for ExpectedPointerMutability {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(codegen_ssa_invalid_sanitize)]
|
|
||||||
#[note]
|
|
||||||
pub(crate) struct InvalidSanitize {
|
|
||||||
#[primary_span]
|
|
||||||
pub span: Span,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(codegen_ssa_target_feature_safe_trait)]
|
#[diag(codegen_ssa_target_feature_safe_trait)]
|
||||||
pub(crate) struct TargetFeatureSafeTrait {
|
pub(crate) struct TargetFeatureSafeTrait {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
|
|||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
use rustc_span::hygiene::Transparency;
|
use rustc_span::hygiene::Transparency;
|
||||||
use rustc_span::{Ident, Span, Symbol};
|
use rustc_span::{Ident, Span, Symbol};
|
||||||
|
pub use rustc_target::spec::SanitizerSet;
|
||||||
use thin_vec::ThinVec;
|
use thin_vec::ThinVec;
|
||||||
|
|
||||||
use crate::attrs::pretty_printing::PrintAttribute;
|
use crate::attrs::pretty_printing::PrintAttribute;
|
||||||
@@ -505,6 +506,12 @@ pub enum AttributeKind {
|
|||||||
/// Represents `#[rustc_object_lifetime_default]`.
|
/// Represents `#[rustc_object_lifetime_default]`.
|
||||||
RustcObjectLifetimeDefault,
|
RustcObjectLifetimeDefault,
|
||||||
|
|
||||||
|
/// Represents `#[sanitize]`
|
||||||
|
///
|
||||||
|
/// the on set and off set are distjoint since there's a third option: unset.
|
||||||
|
/// a node may not set the sanitizer setting in which case it inherits from parents.
|
||||||
|
Sanitize { on_set: SanitizerSet, off_set: SanitizerSet, span: Span },
|
||||||
|
|
||||||
/// Represents `#[should_panic]`
|
/// Represents `#[should_panic]`
|
||||||
ShouldPanic { reason: Option<Symbol>, span: Span },
|
ShouldPanic { reason: Option<Symbol>, span: Span },
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ impl AttributeKind {
|
|||||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||||
RustcObjectLifetimeDefault => No,
|
RustcObjectLifetimeDefault => No,
|
||||||
|
Sanitize { .. } => No,
|
||||||
ShouldPanic { .. } => No,
|
ShouldPanic { .. } => No,
|
||||||
SkipDuringMethodDispatch { .. } => No,
|
SkipDuringMethodDispatch { .. } => No,
|
||||||
SpecializationTrait(..) => No,
|
SpecializationTrait(..) => No,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use rustc_ast::{AttrStyle, IntTy, UintTy};
|
|||||||
use rustc_ast_pretty::pp::Printer;
|
use rustc_ast_pretty::pp::Printer;
|
||||||
use rustc_span::hygiene::Transparency;
|
use rustc_span::hygiene::Transparency;
|
||||||
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
|
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
|
||||||
|
use rustc_target::spec::SanitizerSet;
|
||||||
use thin_vec::ThinVec;
|
use thin_vec::ThinVec;
|
||||||
|
|
||||||
/// This trait is used to print attributes in `rustc_hir_pretty`.
|
/// This trait is used to print attributes in `rustc_hir_pretty`.
|
||||||
@@ -146,4 +147,14 @@ macro_rules! print_tup {
|
|||||||
print_tup!(A B C D E F G H);
|
print_tup!(A B C D E F G H);
|
||||||
print_skip!(Span, (), ErrorGuaranteed);
|
print_skip!(Span, (), ErrorGuaranteed);
|
||||||
print_disp!(u16, bool, NonZero<u32>);
|
print_disp!(u16, bool, NonZero<u32>);
|
||||||
print_debug!(Symbol, Ident, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
|
print_debug!(
|
||||||
|
Symbol,
|
||||||
|
Ident,
|
||||||
|
UintTy,
|
||||||
|
IntTy,
|
||||||
|
Align,
|
||||||
|
AttrStyle,
|
||||||
|
CommentKind,
|
||||||
|
Transparency,
|
||||||
|
SanitizerSet,
|
||||||
|
);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use rustc_feature::{
|
|||||||
ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
|
ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
|
||||||
BuiltinAttribute,
|
BuiltinAttribute,
|
||||||
};
|
};
|
||||||
use rustc_hir::attrs::{AttributeKind, InlineAttr, MirDialect, MirPhase, ReprAttr};
|
use rustc_hir::attrs::{AttributeKind, InlineAttr, MirDialect, MirPhase, ReprAttr, SanitizerSet};
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::LocalModDefId;
|
use rustc_hir::def_id::LocalModDefId;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
@@ -197,6 +197,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||||||
&Attribute::Parsed(AttributeKind::CustomMir(dialect, phase, attr_span)) => {
|
&Attribute::Parsed(AttributeKind::CustomMir(dialect, phase, attr_span)) => {
|
||||||
self.check_custom_mir(dialect, phase, attr_span)
|
self.check_custom_mir(dialect, phase, attr_span)
|
||||||
}
|
}
|
||||||
|
&Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, span: attr_span}) => {
|
||||||
|
self.check_sanitize(attr_span, on_set | off_set, span, target);
|
||||||
|
},
|
||||||
Attribute::Parsed(
|
Attribute::Parsed(
|
||||||
AttributeKind::BodyStability { .. }
|
AttributeKind::BodyStability { .. }
|
||||||
| AttributeKind::ConstStabilityIndirect
|
| AttributeKind::ConstStabilityIndirect
|
||||||
@@ -258,9 +261,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||||||
[sym::diagnostic, sym::on_unimplemented, ..] => {
|
[sym::diagnostic, sym::on_unimplemented, ..] => {
|
||||||
self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
|
self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
|
||||||
}
|
}
|
||||||
[sym::sanitize, ..] => {
|
|
||||||
self.check_sanitize(attr, span, target)
|
|
||||||
}
|
|
||||||
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
|
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
|
||||||
[sym::doc, ..] => self.check_doc_attrs(
|
[sym::doc, ..] => self.check_doc_attrs(
|
||||||
attr,
|
attr,
|
||||||
@@ -483,23 +483,30 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||||||
|
|
||||||
/// Checks that the `#[sanitize(..)]` attribute is applied to a
|
/// Checks that the `#[sanitize(..)]` attribute is applied to a
|
||||||
/// function/closure/method, or to an impl block or module.
|
/// function/closure/method, or to an impl block or module.
|
||||||
fn check_sanitize(&self, attr: &Attribute, target_span: Span, target: Target) {
|
fn check_sanitize(
|
||||||
|
&self,
|
||||||
|
attr_span: Span,
|
||||||
|
set: SanitizerSet,
|
||||||
|
target_span: Span,
|
||||||
|
target: Target,
|
||||||
|
) {
|
||||||
let mut not_fn_impl_mod = None;
|
let mut not_fn_impl_mod = None;
|
||||||
let mut no_body = None;
|
let mut no_body = None;
|
||||||
|
|
||||||
if let Some(list) = attr.meta_item_list() {
|
|
||||||
for item in list.iter() {
|
|
||||||
let MetaItemInner::MetaItem(set) = item else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
|
|
||||||
match target {
|
match target {
|
||||||
Target::Fn
|
Target::Fn
|
||||||
| Target::Closure
|
| Target::Closure
|
||||||
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
|
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
|
||||||
| Target::Impl { .. }
|
| Target::Impl { .. }
|
||||||
| Target::Mod => return,
|
| Target::Mod => return,
|
||||||
Target::Static if matches!(segments.as_slice(), [sym::address]) => return,
|
Target::Static
|
||||||
|
// if we mask out the address bits, i.e. *only* address was set,
|
||||||
|
// we allow it
|
||||||
|
if set & !(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
|
||||||
|
== SanitizerSet::empty() =>
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// These are "functions", but they aren't allowed because they don't
|
// These are "functions", but they aren't allowed because they don't
|
||||||
// have a body, so the usual explanation would be confusing.
|
// have a body, so the usual explanation would be confusing.
|
||||||
@@ -511,15 +518,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||||||
not_fn_impl_mod = Some(target_span);
|
not_fn_impl_mod = Some(target_span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
|
self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
|
||||||
attr_span: attr.span(),
|
attr_span,
|
||||||
not_fn_impl_mod,
|
not_fn_impl_mod,
|
||||||
no_body,
|
no_body,
|
||||||
help: (),
|
help: (),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if `#[naked]` is applied to a function definition.
|
/// Checks if `#[naked]` is applied to a function definition.
|
||||||
fn check_naked(&self, hir_id: HirId, target: Target) {
|
fn check_naked(&self, hir_id: HirId, target: Target) {
|
||||||
|
|||||||
@@ -49,24 +49,6 @@ LL | #[crate_name]
|
|||||||
|
|
|
|
||||||
= note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
|
= note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
|
||||||
|
|
||||||
error: malformed `sanitize` attribute input
|
|
||||||
--> $DIR/malformed-attrs.rs:92:1
|
|
||||||
|
|
|
||||||
LL | #[sanitize]
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
help: the following are the possible correct uses
|
|
||||||
|
|
|
||||||
LL | #[sanitize(address = "on|off")]
|
|
||||||
| ++++++++++++++++++++
|
|
||||||
LL | #[sanitize(cfi = "on|off")]
|
|
||||||
| ++++++++++++++++
|
|
||||||
LL | #[sanitize(hwaddress = "on|off")]
|
|
||||||
| ++++++++++++++++++++++
|
|
||||||
LL | #[sanitize(kcfi = "on|off")]
|
|
||||||
| +++++++++++++++++
|
|
||||||
= and 5 other candidates
|
|
||||||
|
|
||||||
error: malformed `instruction_set` attribute input
|
error: malformed `instruction_set` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:106:1
|
--> $DIR/malformed-attrs.rs:106:1
|
||||||
|
|
|
|
||||||
@@ -543,6 +525,24 @@ LL | #[coverage(off)]
|
|||||||
LL | #[coverage(on)]
|
LL | #[coverage(on)]
|
||||||
| ++++
|
| ++++
|
||||||
|
|
||||||
|
error[E0539]: malformed `sanitize` attribute input
|
||||||
|
--> $DIR/malformed-attrs.rs:92:1
|
||||||
|
|
|
||||||
|
LL | #[sanitize]
|
||||||
|
| ^^^^^^^^^^^ expected this to be a list
|
||||||
|
|
|
||||||
|
help: try changing it to one of the following valid forms of the attribute
|
||||||
|
|
|
||||||
|
LL | #[sanitize(address = "on|off")]
|
||||||
|
| ++++++++++++++++++++
|
||||||
|
LL | #[sanitize(cfi = "on|off")]
|
||||||
|
| ++++++++++++++++
|
||||||
|
LL | #[sanitize(hwaddress = "on|off")]
|
||||||
|
| ++++++++++++++++++++++
|
||||||
|
LL | #[sanitize(kcfi = "on|off")]
|
||||||
|
| +++++++++++++++++
|
||||||
|
= and 5 other candidates
|
||||||
|
|
||||||
error[E0565]: malformed `no_implicit_prelude` attribute input
|
error[E0565]: malformed `no_implicit_prelude` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:97:1
|
--> $DIR/malformed-attrs.rs:97:1
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
#![feature(sanitize)]
|
#![feature(sanitize)]
|
||||||
|
|
||||||
#[sanitize(brontosaurus = "off")] //~ ERROR invalid argument
|
#[sanitize(brontosaurus = "off")] //~ ERROR malformed `sanitize` attribute input
|
||||||
fn main() {
|
fn main() {}
|
||||||
}
|
|
||||||
|
|
||||||
#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
|
#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
|
||||||
#[sanitize(address = "off")]
|
#[sanitize(address = "off")]
|
||||||
@@ -12,11 +11,11 @@ fn multiple_consistent() {}
|
|||||||
#[sanitize(address = "off")]
|
#[sanitize(address = "off")]
|
||||||
fn multiple_inconsistent() {}
|
fn multiple_inconsistent() {}
|
||||||
|
|
||||||
#[sanitize(address = "bogus")] //~ ERROR invalid argument for `sanitize`
|
#[sanitize(address = "bogus")] //~ ERROR malformed `sanitize` attribute input
|
||||||
fn wrong_value() {}
|
fn wrong_value() {}
|
||||||
|
|
||||||
#[sanitize = "off"] //~ ERROR malformed `sanitize` attribute input
|
#[sanitize = "off"] //~ ERROR malformed `sanitize` attribute input
|
||||||
fn name_value () {}
|
fn name_value() {}
|
||||||
|
|
||||||
#[sanitize] //~ ERROR malformed `sanitize` attribute input
|
#[sanitize] //~ ERROR malformed `sanitize` attribute input
|
||||||
fn just_word() {}
|
fn just_word() {}
|
||||||
|
|||||||
@@ -1,10 +1,82 @@
|
|||||||
error: malformed `sanitize` attribute input
|
error[E0539]: malformed `sanitize` attribute input
|
||||||
--> $DIR/invalid-sanitize.rs:18:1
|
--> $DIR/invalid-sanitize.rs:3:1
|
||||||
|
|
|
||||||
|
LL | #[sanitize(brontosaurus = "off")]
|
||||||
|
| ^^^^^^^^^^^------------^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread" or "hwaddress"
|
||||||
|
|
|
||||||
|
help: try changing it to one of the following valid forms of the attribute
|
||||||
|
|
|
||||||
|
LL - #[sanitize(brontosaurus = "off")]
|
||||||
|
LL + #[sanitize(address = "on|off")]
|
||||||
|
|
|
||||||
|
LL - #[sanitize(brontosaurus = "off")]
|
||||||
|
LL + #[sanitize(cfi = "on|off")]
|
||||||
|
|
|
||||||
|
LL - #[sanitize(brontosaurus = "off")]
|
||||||
|
LL + #[sanitize(hwaddress = "on|off")]
|
||||||
|
|
|
||||||
|
LL - #[sanitize(brontosaurus = "off")]
|
||||||
|
LL + #[sanitize(kcfi = "on|off")]
|
||||||
|
|
|
||||||
|
= and 5 other candidates
|
||||||
|
|
||||||
|
error: multiple `sanitize` attributes
|
||||||
|
--> $DIR/invalid-sanitize.rs:6:1
|
||||||
|
|
|
||||||
|
LL | #[sanitize(address = "off")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||||
|
|
|
||||||
|
note: attribute also specified here
|
||||||
|
--> $DIR/invalid-sanitize.rs:7:1
|
||||||
|
|
|
||||||
|
LL | #[sanitize(address = "off")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: multiple `sanitize` attributes
|
||||||
|
--> $DIR/invalid-sanitize.rs:10:1
|
||||||
|
|
|
||||||
|
LL | #[sanitize(address = "on")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||||
|
|
|
||||||
|
note: attribute also specified here
|
||||||
|
--> $DIR/invalid-sanitize.rs:11:1
|
||||||
|
|
|
||||||
|
LL | #[sanitize(address = "off")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0539]: malformed `sanitize` attribute input
|
||||||
|
--> $DIR/invalid-sanitize.rs:14:1
|
||||||
|
|
|
||||||
|
LL | #[sanitize(address = "bogus")]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^-------^^
|
||||||
|
| |
|
||||||
|
| valid arguments are "on" or "off"
|
||||||
|
|
|
||||||
|
help: try changing it to one of the following valid forms of the attribute
|
||||||
|
|
|
||||||
|
LL - #[sanitize(address = "bogus")]
|
||||||
|
LL + #[sanitize(address = "on|off")]
|
||||||
|
|
|
||||||
|
LL - #[sanitize(address = "bogus")]
|
||||||
|
LL + #[sanitize(cfi = "on|off")]
|
||||||
|
|
|
||||||
|
LL - #[sanitize(address = "bogus")]
|
||||||
|
LL + #[sanitize(hwaddress = "on|off")]
|
||||||
|
|
|
||||||
|
LL - #[sanitize(address = "bogus")]
|
||||||
|
LL + #[sanitize(kcfi = "on|off")]
|
||||||
|
|
|
||||||
|
= and 5 other candidates
|
||||||
|
|
||||||
|
error[E0539]: malformed `sanitize` attribute input
|
||||||
|
--> $DIR/invalid-sanitize.rs:17:1
|
||||||
|
|
|
|
||||||
LL | #[sanitize = "off"]
|
LL | #[sanitize = "off"]
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^ expected this to be a list
|
||||||
|
|
|
|
||||||
help: the following are the possible correct uses
|
help: try changing it to one of the following valid forms of the attribute
|
||||||
|
|
|
|
||||||
LL - #[sanitize = "off"]
|
LL - #[sanitize = "off"]
|
||||||
LL + #[sanitize(address = "on|off")]
|
LL + #[sanitize(address = "on|off")]
|
||||||
@@ -20,13 +92,13 @@ LL + #[sanitize(kcfi = "on|off")]
|
|||||||
|
|
|
|
||||||
= and 5 other candidates
|
= and 5 other candidates
|
||||||
|
|
||||||
error: malformed `sanitize` attribute input
|
error[E0539]: malformed `sanitize` attribute input
|
||||||
--> $DIR/invalid-sanitize.rs:21:1
|
--> $DIR/invalid-sanitize.rs:20:1
|
||||||
|
|
|
|
||||||
LL | #[sanitize]
|
LL | #[sanitize]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^ expected this to be a list
|
||||||
|
|
|
|
||||||
help: the following are the possible correct uses
|
help: try changing it to one of the following valid forms of the attribute
|
||||||
|
|
|
|
||||||
LL | #[sanitize(address = "on|off")]
|
LL | #[sanitize(address = "on|off")]
|
||||||
| ++++++++++++++++++++
|
| ++++++++++++++++++++
|
||||||
@@ -38,45 +110,6 @@ LL | #[sanitize(kcfi = "on|off")]
|
|||||||
| +++++++++++++++++
|
| +++++++++++++++++
|
||||||
= and 5 other candidates
|
= and 5 other candidates
|
||||||
|
|
||||||
error: multiple `sanitize` attributes
|
|
||||||
--> $DIR/invalid-sanitize.rs:7:1
|
|
||||||
|
|
|
||||||
LL | #[sanitize(address = "off")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
|
||||||
|
|
|
||||||
note: attribute also specified here
|
|
||||||
--> $DIR/invalid-sanitize.rs:8:1
|
|
||||||
|
|
|
||||||
LL | #[sanitize(address = "off")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: multiple `sanitize` attributes
|
|
||||||
--> $DIR/invalid-sanitize.rs:11:1
|
|
||||||
|
|
|
||||||
LL | #[sanitize(address = "on")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
|
||||||
|
|
|
||||||
note: attribute also specified here
|
|
||||||
--> $DIR/invalid-sanitize.rs:12:1
|
|
||||||
|
|
|
||||||
LL | #[sanitize(address = "off")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: invalid argument for `sanitize`
|
|
||||||
--> $DIR/invalid-sanitize.rs:3:1
|
|
||||||
|
|
|
||||||
LL | #[sanitize(brontosaurus = "off")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
|
|
||||||
|
|
||||||
error: invalid argument for `sanitize`
|
|
||||||
--> $DIR/invalid-sanitize.rs:15:1
|
|
||||||
|
|
|
||||||
LL | #[sanitize(address = "bogus")]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
|
|
||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0539`.
|
||||||
|
|||||||
Reference in New Issue
Block a user