Rollup merge of #145670 - jdonszelmann:port-sanitize, r=lcnr

port `sanitize` attribute to the new parsing infrastructure
This commit is contained in:
Samuel Tardieu 2025-08-23 22:22:17 +02:00 committed by GitHub
commit e7dc14e59b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 291 additions and 201 deletions

View File

@ -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 super::prelude::*;
@ -464,6 +464,12 @@ impl<S: Stage> CombineAttributeParser<S> for ForceTargetFeatureParser {
was_forced: true,
};
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>(
cx: &'c mut AcceptContext<'_, '_, S>,
@ -471,11 +477,106 @@ impl<S: Stage> CombineAttributeParser<S> for ForceTargetFeatureParser {
) -> impl IntoIterator<Item = Self::Item> + 'c {
parse_tf_attribute(cx, args)
}
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)),
]);
}
pub(crate) struct SanitizeParser;
impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
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 })
}
}

View File

@ -20,7 +20,8 @@ use crate::attributes::allow_unstable::{
use crate::attributes::body::CoroutineParser;
use crate::attributes::codegen_attrs::{
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
NoMangleParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
NoMangleParser, OptimizeParser, SanitizeParser, TargetFeatureParser, TrackCallerParser,
UsedParser,
};
use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::deprecation::DeprecationParser;
@ -184,6 +185,7 @@ attribute_parsers!(
Single<RustcLayoutScalarValidRangeEnd>,
Single<RustcLayoutScalarValidRangeStart>,
Single<RustcObjectLifetimeDefaultParser>,
Single<SanitizeParser>,
Single<ShouldPanicParser>,
Single<SkipDuringMethodDispatchParser>,
Single<TransparencyParser>,

View File

@ -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_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_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64

View File

@ -293,6 +293,9 @@ fn process_builtin_attrs(
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
}
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
sym::sanitize => interesting_spans.sanitize = Some(attr.span()),
sym::instruction_set => {
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 {
// 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).
Some(parent) => tcx.disabled_sanitizers_for(parent),
// 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.
if let Some(attr) = tcx.get_attr(did, sym::sanitize) {
return parse_sanitize_attr(tcx, attr, disabled);
if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set))
{
// 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
}

View File

@ -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)]
#[diag(codegen_ssa_target_feature_safe_trait)]
pub(crate) struct TargetFeatureSafeTrait {

View File

@ -10,6 +10,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
use rustc_span::def_id::DefId;
use rustc_span::hygiene::Transparency;
use rustc_span::{Ident, Span, Symbol};
pub use rustc_target::spec::SanitizerSet;
use thin_vec::ThinVec;
use crate::attrs::pretty_printing::PrintAttribute;
@ -505,6 +506,12 @@ pub enum AttributeKind {
/// Represents `#[rustc_object_lifetime_default]`.
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]`
ShouldPanic { reason: Option<Symbol>, span: Span },

View File

@ -73,6 +73,7 @@ impl AttributeKind {
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,
RustcObjectLifetimeDefault => No,
Sanitize { .. } => No,
ShouldPanic { .. } => No,
SkipDuringMethodDispatch { .. } => No,
SpecializationTrait(..) => No,

View File

@ -6,6 +6,7 @@ use rustc_ast::{AttrStyle, IntTy, UintTy};
use rustc_ast_pretty::pp::Printer;
use rustc_span::hygiene::Transparency;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
use rustc_target::spec::SanitizerSet;
use thin_vec::ThinVec;
/// 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_skip!(Span, (), ErrorGuaranteed);
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,
);

View File

@ -18,7 +18,7 @@ use rustc_feature::{
ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
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_id::LocalModDefId;
use rustc_hir::intravisit::{self, Visitor};
@ -197,6 +197,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
&Attribute::Parsed(AttributeKind::CustomMir(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(
AttributeKind::BodyStability { .. }
| AttributeKind::ConstStabilityIndirect
@ -258,9 +261,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::diagnostic, sym::on_unimplemented, ..] => {
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::doc, ..] => self.check_doc_attrs(
attr,
@ -483,42 +483,48 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
/// Checks that the `#[sanitize(..)]` attribute is applied to a
/// 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 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 {
Target::Fn
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
| Target::Impl { .. }
| Target::Mod => return,
Target::Static if matches!(segments.as_slice(), [sym::address]) => return,
// These are "functions", but they aren't allowed because they don't
// have a body, so the usual explanation would be confusing.
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
no_body = Some(target_span);
}
_ => {
not_fn_impl_mod = Some(target_span);
}
}
match target {
Target::Fn
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
| Target::Impl { .. }
| Target::Mod => 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
// have a body, so the usual explanation would be confusing.
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
no_body = Some(target_span);
}
_ => {
not_fn_impl_mod = Some(target_span);
}
self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
attr_span: attr.span(),
not_fn_impl_mod,
no_body,
help: (),
});
}
self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
attr_span,
not_fn_impl_mod,
no_body,
help: (),
});
}
/// Checks if `#[naked]` is applied to a function definition.

View File

@ -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>
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
--> $DIR/malformed-attrs.rs:106:1
|
@ -543,6 +525,24 @@ LL | #[coverage(off)]
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
--> $DIR/malformed-attrs.rs:97:1
|

View File

@ -1,8 +1,7 @@
#![feature(sanitize)]
#[sanitize(brontosaurus = "off")] //~ ERROR invalid argument
fn main() {
}
#[sanitize(brontosaurus = "off")] //~ ERROR malformed `sanitize` attribute input
fn main() {}
#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
#[sanitize(address = "off")]
@ -12,11 +11,11 @@ fn multiple_consistent() {}
#[sanitize(address = "off")]
fn multiple_inconsistent() {}
#[sanitize(address = "bogus")] //~ ERROR invalid argument for `sanitize`
#[sanitize(address = "bogus")] //~ ERROR malformed `sanitize` attribute input
fn wrong_value() {}
#[sanitize = "off"] //~ ERROR malformed `sanitize` attribute input
fn name_value () {}
fn name_value() {}
#[sanitize] //~ ERROR malformed `sanitize` attribute input
fn just_word() {}

View File

@ -1,10 +1,82 @@
error: malformed `sanitize` attribute input
--> $DIR/invalid-sanitize.rs:18:1
error[E0539]: malformed `sanitize` attribute input
--> $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"]
| ^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^ 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(address = "on|off")]
@ -20,13 +92,13 @@ LL + #[sanitize(kcfi = "on|off")]
|
= and 5 other candidates
error: malformed `sanitize` attribute input
--> $DIR/invalid-sanitize.rs:21:1
error[E0539]: malformed `sanitize` attribute input
--> $DIR/invalid-sanitize.rs:20:1
|
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")]
| ++++++++++++++++++++
@ -38,45 +110,6 @@ LL | #[sanitize(kcfi = "on|off")]
| +++++++++++++++++
= 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
For more information about this error, try `rustc --explain E0539`.