diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 5322fe58cf337..6901d6f83ffff 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -169,8 +169,8 @@ 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_no_sanitize = invalid argument for `no_sanitize` - .note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread` +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 diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 0b31fa8fa886b..075c3b6ab607d 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -9,7 +9,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; -use rustc_hir::{self as hir, HirId, LangItem, lang_items}; +use rustc_hir::{self as hir, Attribute, HirId, LangItem, lang_items}; use rustc_middle::middle::codegen_fn_attrs::{ CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, }; @@ -85,7 +85,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { let mut inline_span = None; let mut link_ordinal_span = None; - let mut no_sanitize_span = None; + let mut sanitize_span = None; let mut mixed_export_name_no_mangle_lint_state = MixedExportNameAndNoMangleState::default(); let mut no_mangle_span = None; @@ -320,39 +320,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.link_ordinal = ordinal; } } - sym::no_sanitize => { - no_sanitize_span = Some(attr.span()); - if let Some(list) = attr.meta_item_list() { - for item in list.iter() { - match item.name() { - Some(sym::address) => { - codegen_fn_attrs.no_sanitize |= - SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS - } - Some(sym::cfi) => codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI, - Some(sym::kcfi) => codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI, - Some(sym::memory) => { - codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY - } - Some(sym::memtag) => { - codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMTAG - } - Some(sym::shadow_call_stack) => { - codegen_fn_attrs.no_sanitize |= SanitizerSet::SHADOWCALLSTACK - } - Some(sym::thread) => { - codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD - } - Some(sym::hwaddress) => { - codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS - } - _ => { - tcx.dcx().emit_err(errors::InvalidNoSanitize { span: item.span() }); - } - } - } - } - } + sym::sanitize => sanitize_span = Some(attr.span()), sym::instruction_set => { codegen_fn_attrs.instruction_set = attr.meta_item_list().and_then(|l| match &l[..] { @@ -447,6 +415,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } + codegen_fn_attrs.no_sanitize |= tcx.disabled_sanitizers_for(did); mixed_export_name_no_mangle_lint_state.lint_if_mixed(tcx); codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| { @@ -572,11 +541,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { if !codegen_fn_attrs.no_sanitize.is_empty() && codegen_fn_attrs.inline.always() - && let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) + && let (Some(sanitize_span), Some(inline_span)) = (sanitize_span, inline_span) { let hir_id = tcx.local_def_id_to_hir_id(did); - tcx.node_span_lint(lint::builtin::INLINE_NO_SANITIZE, hir_id, no_sanitize_span, |lint| { - lint.primary_message("`no_sanitize` will have no effect after inlining"); + tcx.node_span_lint(lint::builtin::INLINE_NO_SANITIZE, hir_id, sanitize_span, |lint| { + lint.primary_message("setting `sanitize` off will have no effect after inlining"); lint.span_note(inline_span, "inlining requested here"); }) } @@ -660,6 +629,87 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs } +/// For an attr that has the `sanitize` attribute, read the list of +/// disabled sanitizers. +fn parse_sanitize_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> SanitizerSet { + let mut result = SanitizerSet::empty(); + 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::>(); + 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 { + // 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); + } + + // Otherwise backtrack. + 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 + // there is no sanitizers to exclude. + None => SanitizerSet::empty(), + } +} + /// Given a map from target_features to whether they are enabled or disabled, ensure only valid /// combinations are allowed. pub fn check_tied_features( @@ -900,5 +950,10 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option { } pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers }; + *providers = Providers { + codegen_fn_attrs, + should_inherit_track_caller, + disabled_sanitizers_for, + ..*providers + }; } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index bac02bdf983a4..b4402cc917cc3 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -1137,9 +1137,9 @@ impl IntoDiagArg for ExpectedPointerMutability { } #[derive(Diagnostic)] -#[diag(codegen_ssa_invalid_no_sanitize)] +#[diag(codegen_ssa_invalid_sanitize)] #[note] -pub(crate) struct InvalidNoSanitize { +pub(crate) struct InvalidSanitize { #[primary_span] pub span: Span, } diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 7d6e471e7e951..0d9b0b3576623 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -522,9 +522,8 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(track_caller, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes), ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding, EncodeCrossCrate::No), gated!( - no_sanitize, Normal, - template!(List: "address, kcfi, memory, thread"), DuplicatesOk, - EncodeCrossCrate::No, experimental!(no_sanitize) + sanitize, Normal, template!(List: r#"address = "on|off", cfi = "on|off""#), ErrorPreceding, + EncodeCrossCrate::No, sanitize, experimental!(sanitize), ), gated!( coverage, Normal, template!(OneOf: &[sym::off, sym::on]), diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 0cd090b25a4f8..39bbcc7ccc6a8 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -186,6 +186,9 @@ declare_features! ( (removed, no_coverage, "1.74.0", Some(84605), Some("renamed to `coverage_attribute`"), 114656), /// Allows `#[no_debug]`. (removed, no_debug, "1.43.0", Some(29721), Some("removed due to lack of demand"), 69667), + // Allows the use of `no_sanitize` attribute. + /// The feature was renamed to `sanitize` and the attribute to `#[sanitize(xyz = "on|off")]` + (removed, no_sanitize, "CURRENT_RUSTC_VERSION", Some(39699), Some(r#"renamed to sanitize(xyz = "on|off")"#), 1234), /// Note: this feature was previously recorded in a separate /// `STABLE_REMOVED` list because it, uniquely, was once stable but was /// then removed. But there was no utility storing it separately, so now diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index bd6ea85014767..5fb9f018fe265 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -593,8 +593,6 @@ declare_features! ( (unstable, new_range, "1.86.0", Some(123741)), /// Allows `#![no_core]`. (unstable, no_core, "1.3.0", Some(29639)), - /// Allows the use of `no_sanitize` attribute. - (unstable, no_sanitize, "1.42.0", Some(39699)), /// Allows using the `non_exhaustive_omitted_patterns` lint. (unstable, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554)), /// Allows `for` binders in where-clauses @@ -627,6 +625,8 @@ declare_features! ( (unstable, return_type_notation, "1.70.0", Some(109417)), /// Allows `extern "rust-cold"`. (unstable, rust_cold_cc, "1.63.0", Some(97544)), + /// Allows the use of the `sanitize` attribute. + (unstable, sanitize, "CURRENT_RUSTC_VERSION", Some(39699)), /// Allows the use of SIMD types in functions declared in `extern` blocks. (unstable, simd_ffi, "1.0.0", Some(27731)), /// Allows specialization of implementations (RFC 1210). diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index b0ea9689e50d6..d77d5073d1d18 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2296,18 +2296,18 @@ declare_lint! { declare_lint! { /// The `inline_no_sanitize` lint detects incompatible use of - /// [`#[inline(always)]`][inline] and [`#[no_sanitize(...)]`][no_sanitize]. + /// [`#[inline(always)]`][inline] and [`#[sanitize(xyz = "off")]`][sanitize]. /// /// [inline]: https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute - /// [no_sanitize]: https://doc.rust-lang.org/nightly/unstable-book/language-features/no-sanitize.html + /// [sanitize]: https://doc.rust-lang.org/nightly/unstable-book/language-features/no-sanitize.html /// /// ### Example /// /// ```rust - /// #![feature(no_sanitize)] + /// #![feature(sanitize)] /// /// #[inline(always)] - /// #[no_sanitize(address)] + /// #[sanitize(address = "off")] /// fn x() {} /// /// fn main() { @@ -2320,11 +2320,11 @@ declare_lint! { /// ### Explanation /// /// The use of the [`#[inline(always)]`][inline] attribute prevents the - /// the [`#[no_sanitize(...)]`][no_sanitize] attribute from working. + /// the [`#[sanitize(xyz = "off")]`][sanitize] attribute from working. /// Consider temporarily removing `inline` attribute. pub INLINE_NO_SANITIZE, Warn, - "detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`", + r#"detects incompatible use of `#[inline(always)]` and `#[sanitize(... = "off")]`"#, } declare_lint! { diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index f21cf5fa45e69..9652f9c330fae 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -40,8 +40,8 @@ pub struct CodegenFnAttrs { /// The `#[link_section = "..."]` attribute, or what executable section this /// should be placed in. pub link_section: Option, - /// The `#[no_sanitize(...)]` attribute. Indicates sanitizers for which - /// instrumentation should be disabled inside the annotated function. + /// The `#[sanitize(xyz = "off")]` attribute. Indicates sanitizers for which + /// instrumentation should be disabled inside the function. pub no_sanitize: SanitizerSet, /// The `#[instruction_set(set)]` attribute. Indicates if the generated code should /// be generated against a specific instruction set. Only usable on architectures which allow diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 7c998761a9d44..7dc9b0401d0ce 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -342,6 +342,7 @@ trivial! { rustc_span::Symbol, rustc_span::Ident, rustc_target::spec::PanicStrategy, + rustc_target::spec::SanitizerSet, rustc_type_ir::Variance, u32, usize, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 63312eff49066..360c05029d09f 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -99,7 +99,7 @@ use rustc_session::lint::LintExpectationId; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span, Symbol}; -use rustc_target::spec::PanicStrategy; +use rustc_target::spec::{PanicStrategy, SanitizerSet}; use {rustc_abi as abi, rustc_ast as ast, rustc_attr_data_structures as attr, rustc_hir as hir}; use crate::infer::canonical::{self, Canonical}; @@ -2653,6 +2653,16 @@ rustc_queries! { desc { |tcx| "looking up anon const kind of `{}`", tcx.def_path_str(def_id) } separate_provide_extern } + + /// Checks for the nearest `#[sanitize(xyz = "off")]` or + /// `#[sanitize(xyz = "on")]` on this def and any enclosing defs, up to the + /// crate root. + /// + /// Returns the set of sanitizers that is explicitly disabled for this def. + query disabled_sanitizers_for(key: LocalDefId) -> SanitizerSet { + desc { |tcx| "checking what set of sanitizers are enabled on `{}`", tcx.def_path_str(key) } + feedable + } } rustc_with_all_queries! { define_callbacks! } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 7c237d708c0ad..d72121c6939c7 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -526,10 +526,6 @@ passes_no_mangle_foreign = .note = symbol names in extern blocks are not mangled .suggestion = remove this attribute -passes_no_sanitize = - `#[no_sanitize({$attr_str})]` should be applied to {$accepted_kind} - .label = not {$accepted_kind} - passes_non_exaustive_with_default_field_values = `#[non_exhaustive]` can't be used to annotate items with default field values .label = this struct has default field values @@ -654,6 +650,12 @@ passes_rustc_std_internal_symbol = attribute should be applied to functions or statics .label = not a function or static +passes_sanitize_attribute_not_allowed = + sanitize attribute not allowed here + .not_fn_impl_mod = not a function, impl block, or module + .no_body = function has no body + .help = sanitize attribute can be applied to a function (with body), impl block, or module + passes_should_be_applied_to_fn = attribute should be applied to a function definition .label = {$on_crate -> diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dddbf65db72ea..96714da371401 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -161,8 +161,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::inline, ..] => self.check_inline(hir_id, attr, span, target), [sym::coverage, ..] => self.check_coverage(attr, span, target), [sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target), - [sym::no_sanitize, ..] => { - self.check_no_sanitize(attr, span, target) + [sym::sanitize, ..] => { + self.check_sanitize(attr, span, target) } [sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target, item), [sym::marker, ..] => self.check_marker(hir_id, attr, span, target), @@ -534,39 +534,43 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) { + /// 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) { + 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 sym = item.name(); - match sym { - Some(s @ sym::address | s @ sym::hwaddress) => { - let is_valid = - matches!(target, Target::Fn | Target::Method(..) | Target::Static); - if !is_valid { - self.dcx().emit_err(errors::NoSanitize { - attr_span: item.span(), - defn_span: span, - accepted_kind: "a function or static", - attr_str: s.as_str(), - }); - } + let MetaItemInner::MetaItem(set) = item else { + return; + }; + let segments = set.path.segments.iter().map(|x| x.ident.name).collect::>(); + 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); } + _ => { - let is_valid = matches!(target, Target::Fn | Target::Method(..)); - if !is_valid { - self.dcx().emit_err(errors::NoSanitize { - attr_span: item.span(), - defn_span: span, - accepted_kind: "a function", - attr_str: &match sym { - Some(name) => name.to_string(), - None => "...".to_string(), - }, - }); - } + not_fn_impl_mod = Some(target_span); } } } + self.dcx().emit_err(errors::SanitizeAttributeNotAllowed { + attr_span: attr.span(), + not_fn_impl_mod, + no_body, + help: (), + }); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index f0d4b610f6384..56f1eaca3c4ef 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1743,15 +1743,21 @@ pub(crate) struct AttrCrateLevelOnlySugg { pub attr: Span, } +/// "sanitize attribute not allowed here" #[derive(Diagnostic)] -#[diag(passes_no_sanitize)] -pub(crate) struct NoSanitize<'a> { +#[diag(passes_sanitize_attribute_not_allowed)] +pub(crate) struct SanitizeAttributeNotAllowed { #[primary_span] pub attr_span: Span, - #[label] - pub defn_span: Span, - pub accepted_kind: &'a str, - pub attr_str: &'a str, + /// "not a function, impl block, or module" + #[label(passes_not_fn_impl_mod)] + pub not_fn_impl_mod: Option, + /// "function has no body" + #[label(passes_no_body)] + pub no_body: Option, + /// "sanitize attribute can be applied to a function (with body), impl block, or module" + #[help] + pub help: (), } // FIXME(jdonszelmann): move back to rustc_attr diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index cb9ccf4cc3f23..55532779a5a6f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1243,6 +1243,7 @@ symbols! { iterator, iterator_collect_fn, kcfi, + kernel_address, keylocker_x86, keyword, kind, diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index b1654b15e0819..c971c359b4b47 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -45,7 +45,7 @@ implementation: [marked][sanitizer-attribute] with appropriate LLVM attribute: `SanitizeAddress`, `SanitizeHWAddress`, `SanitizeMemory`, or `SanitizeThread`. By default all functions are instrumented, but this - behaviour can be changed with `#[no_sanitize(...)]`. + behaviour can be changed with `#[sanitize(xyz = "on|off")]`. * The decision whether to perform instrumentation or not is possible only at a function granularity. In the cases were those decision differ between diff --git a/src/doc/unstable-book/src/language-features/no-sanitize.md b/src/doc/unstable-book/src/language-features/no-sanitize.md deleted file mode 100644 index 28c683934d4ed..0000000000000 --- a/src/doc/unstable-book/src/language-features/no-sanitize.md +++ /dev/null @@ -1,29 +0,0 @@ -# `no_sanitize` - -The tracking issue for this feature is: [#39699] - -[#39699]: https://github.com/rust-lang/rust/issues/39699 - ------------------------- - -The `no_sanitize` attribute can be used to selectively disable sanitizer -instrumentation in an annotated function. This might be useful to: avoid -instrumentation overhead in a performance critical function, or avoid -instrumenting code that contains constructs unsupported by given sanitizer. - -The precise effect of this annotation depends on particular sanitizer in use. -For example, with `no_sanitize(thread)`, the thread sanitizer will no longer -instrument non-atomic store / load operations, but it will instrument atomic -operations to avoid reporting false positives and provide meaning full stack -traces. - -## Examples - -``` rust -#![feature(no_sanitize)] - -#[no_sanitize(address)] -fn foo() { - // ... -} -``` diff --git a/src/doc/unstable-book/src/language-features/sanitize.md b/src/doc/unstable-book/src/language-features/sanitize.md new file mode 100644 index 0000000000000..24591b93bae6c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/sanitize.md @@ -0,0 +1,73 @@ +# `sanitize` + +The tracking issue for this feature is: [#39699] + +[#39699]: https://github.com/rust-lang/rust/issues/39699 + +------------------------ + +The `sanitize` attribute can be used to selectively disable or enable sanitizer +instrumentation in an annotated function. This might be useful to: avoid +instrumentation overhead in a performance critical function, or avoid +instrumenting code that contains constructs unsupported by given sanitizer. + +The precise effect of this annotation depends on particular sanitizer in use. +For example, with `sanitize(thread = "off")`, the thread sanitizer will no +longer instrument non-atomic store / load operations, but it will instrument +atomic operations to avoid reporting false positives and provide meaning full +stack traces. + +This attribute was previously named `no_sanitized`. + +## Examples + +``` rust +#![feature(sanitize)] + +#[sanitize(address = "off")] +fn foo() { + // ... +} +``` + +It is also possible to disable sanitizers for entire modules and enable them +for single items or functions. + +```rust +#![feature(sanitize)] + +#[sanitize(address = "off")] +mod foo { + fn unsanitized() { + // ... + } + + #[sanitize(address = "on")] + fn sanitized() { + // ... + } +} +``` + +It's also applicable to impl blocks. + +```rust +#![feature(sanitize)] + +trait MyTrait { + fn foo(&self); + fn bar(&self); +} + +#[sanitize(address = "off")] +impl MyTrait for () { + fn foo(&self) { + // ... + } + + #[sanitize(address = "on")] + fn bar(&self) { + // ... + } +} +``` diff --git a/tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs b/tests/codegen/sanitizer/cfi/emit-type-checks-attr-sanitize-off.rs similarity index 84% rename from tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs rename to tests/codegen/sanitizer/cfi/emit-type-checks-attr-sanitize-off.rs index 71ccdc8ca624f..651afb3322869 100644 --- a/tests/codegen/sanitizer/cfi/emit-type-checks-attr-no-sanitize.rs +++ b/tests/codegen/sanitizer/cfi/emit-type-checks-attr-sanitize-off.rs @@ -4,11 +4,11 @@ //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Copt-level=0 #![crate_type = "lib"] -#![feature(no_sanitize)] +#![feature(sanitize)] -#[no_sanitize(cfi)] +#[sanitize(cfi = "off")] pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { - // CHECK-LABEL: emit_type_checks_attr_no_sanitize::foo + // CHECK-LABEL: emit_type_checks_attr_sanitize_off::foo // CHECK: Function Attrs: {{.*}} // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: start: diff --git a/tests/codegen/sanitizer/kasan-emits-instrumentation.rs b/tests/codegen/sanitizer/kasan-emits-instrumentation.rs index 774c9ab53f1e7..c70aae1703eff 100644 --- a/tests/codegen/sanitizer/kasan-emits-instrumentation.rs +++ b/tests/codegen/sanitizer/kasan-emits-instrumentation.rs @@ -13,7 +13,7 @@ //@[x86_64] needs-llvm-components: x86 #![crate_type = "rlib"] -#![feature(no_core, no_sanitize, lang_items)] +#![feature(no_core, sanitize, lang_items)] #![no_core] extern crate minicore; @@ -25,7 +25,7 @@ use minicore::*; // CHECK: start: // CHECK-NOT: call void @__asan_report_load // CHECK: } -#[no_sanitize(address)] +#[sanitize(address = "off")] pub fn unsanitized(b: &mut u8) -> u8 { *b } diff --git a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-sanitize-off.rs similarity index 85% rename from tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs rename to tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-sanitize-off.rs index 6b40918dd3af1..e51aef0d0b047 100644 --- a/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs +++ b/tests/codegen/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-sanitize-off.rs @@ -9,15 +9,15 @@ //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 #![crate_type = "lib"] -#![feature(no_core, no_sanitize, lang_items)] +#![feature(no_core, sanitize, lang_items)] #![no_core] extern crate minicore; use minicore::*; -#[no_sanitize(kcfi)] +#[sanitize(kcfi = "off")] pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { - // CHECK-LABEL: emit_kcfi_operand_bundle_attr_no_sanitize::foo + // CHECK-LABEL: emit_kcfi_operand_bundle_attr_sanitize_off::foo // CHECK: Function Attrs: {{.*}} // CHECK-LABEL: define{{.*}}foo{{.*}}!{{|kcfi_type}} !{{[0-9]+}} // CHECK: start: diff --git a/tests/codegen/sanitizer/sanitize-off-asan-kasan.rs b/tests/codegen/sanitizer/sanitize-off-asan-kasan.rs new file mode 100644 index 0000000000000..37549aba4477b --- /dev/null +++ b/tests/codegen/sanitizer/sanitize-off-asan-kasan.rs @@ -0,0 +1,42 @@ +// Verifies that the `#[sanitize(address = "off")]` attribute also turns off +// the kernel address sanitizer. +// +//@ add-core-stubs +//@ compile-flags: -Zsanitizer=kernel-address -Ctarget-feature=-crt-static -Copt-level=0 +//@ revisions: aarch64 riscv64imac riscv64gc x86_64 +//@[aarch64] compile-flags: --target aarch64-unknown-none +//@[aarch64] needs-llvm-components: aarch64 +//@[riscv64imac] compile-flags: --target riscv64imac-unknown-none-elf +//@[riscv64imac] needs-llvm-components: riscv +//@[riscv64gc] compile-flags: --target riscv64gc-unknown-none-elf +//@[riscv64gc] needs-llvm-components: riscv +//@[x86_64] compile-flags: --target x86_64-unknown-none +//@[x86_64] needs-llvm-components: x86 + +#![crate_type = "rlib"] +#![feature(no_core, sanitize, lang_items)] +#![no_core] + +extern crate minicore; +use minicore::*; + +// CHECK-LABEL: ; sanitize_off_asan_kasan::unsanitized +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: sanitize_address +// CHECK: start: +// CHECK-NOT: call void @__asan_report_load +// CHECK: } +#[sanitize(address = "off")] +pub fn unsanitized(b: &mut u8) -> u8 { + *b +} + +// CHECK-LABEL: ; sanitize_off_asan_kasan::sanitized +// CHECK-NEXT: ; Function Attrs: +// CHECK: sanitize_address +// CHECK: start: +// CHECK: call void @__asan_report_load +// CHECK: } +pub fn sanitized(b: &mut u8) -> u8 { + *b +} diff --git a/tests/codegen/sanitizer/no-sanitize-inlining.rs b/tests/codegen/sanitizer/sanitize-off-inlining.rs similarity index 84% rename from tests/codegen/sanitizer/no-sanitize-inlining.rs rename to tests/codegen/sanitizer/sanitize-off-inlining.rs index 4bd832d2ab195..69771827c3a7e 100644 --- a/tests/codegen/sanitizer/no-sanitize-inlining.rs +++ b/tests/codegen/sanitizer/sanitize-off-inlining.rs @@ -1,4 +1,4 @@ -// Verifies that no_sanitize attribute prevents inlining when +// Verifies that sanitize(xyz = "off") attribute prevents inlining when // given sanitizer is enabled, but has no effect on inlining otherwise. // //@ needs-sanitizer-address @@ -9,7 +9,7 @@ //@[LSAN] compile-flags: -Zsanitizer=leak #![crate_type = "lib"] -#![feature(no_sanitize)] +#![feature(sanitize)] // ASAN-LABEL: define void @test // ASAN: call {{.*}} @random_inline @@ -23,7 +23,7 @@ pub fn test(n: &mut u32) { random_inline(n); } -#[no_sanitize(address)] +#[sanitize(address = "off")] #[inline] #[no_mangle] pub fn random_inline(n: &mut u32) { diff --git a/tests/codegen/sanitizer/no-sanitize.rs b/tests/codegen/sanitizer/sanitize-off-kasan-asan.rs similarity index 52% rename from tests/codegen/sanitizer/no-sanitize.rs rename to tests/codegen/sanitizer/sanitize-off-kasan-asan.rs index 2a309f6b9c696..94945f2b2e6ec 100644 --- a/tests/codegen/sanitizer/no-sanitize.rs +++ b/tests/codegen/sanitizer/sanitize-off-kasan-asan.rs @@ -1,34 +1,24 @@ -// Verifies that no_sanitize attribute can be used to -// selectively disable sanitizer instrumentation. +// Verifies that the `#[sanitize(kernel_address = "off")]` attribute also turns off +// the address sanitizer. // //@ needs-sanitizer-address //@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static -Copt-level=0 #![crate_type = "lib"] -#![feature(no_sanitize)] +#![feature(sanitize)] -// CHECK: @UNSANITIZED = constant{{.*}} no_sanitize_address -// CHECK-NOT: @__asan_global_UNSANITIZED -#[no_mangle] -#[no_sanitize(address)] -pub static UNSANITIZED: u32 = 0; - -// CHECK: @__asan_global_SANITIZED -#[no_mangle] -pub static SANITIZED: u32 = 0; - -// CHECK-LABEL: ; no_sanitize::unsanitized +// CHECK-LABEL: ; sanitize_off_kasan_asan::unsanitized // CHECK-NEXT: ; Function Attrs: // CHECK-NOT: sanitize_address // CHECK: start: // CHECK-NOT: call void @__asan_report_load // CHECK: } -#[no_sanitize(address)] +#[sanitize(kernel_address = "off")] pub fn unsanitized(b: &mut u8) -> u8 { *b } -// CHECK-LABEL: ; no_sanitize::sanitized +// CHECK-LABEL: ; sanitize_off_kasan_asan::sanitized // CHECK-NEXT: ; Function Attrs: // CHECK: sanitize_address // CHECK: start: diff --git a/tests/codegen/sanitizer/sanitize-off.rs b/tests/codegen/sanitizer/sanitize-off.rs new file mode 100644 index 0000000000000..0b0c01ed96267 --- /dev/null +++ b/tests/codegen/sanitizer/sanitize-off.rs @@ -0,0 +1,118 @@ +// Verifies that the `#[sanitize(address = "off")]` attribute can be used to +// selectively disable sanitizer instrumentation. +// +//@ needs-sanitizer-address +//@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static -Copt-level=0 + +#![crate_type = "lib"] +#![feature(sanitize)] + +// CHECK: @UNSANITIZED = constant{{.*}} no_sanitize_address +// CHECK-NOT: @__asan_global_SANITIZED +#[no_mangle] +#[sanitize(address = "off")] +pub static UNSANITIZED: u32 = 0; + +// CHECK: @__asan_global_SANITIZED +#[no_mangle] +pub static SANITIZED: u32 = 0; + +// CHECK-LABEL: ; sanitize_off::unsanitized +// CHECK-NEXT: ; Function Attrs: +// CHECK-NOT: sanitize_address +// CHECK: start: +// CHECK-NOT: call void @__asan_report_load +// CHECK: } +#[sanitize(address = "off")] +pub fn unsanitized(b: &mut u8) -> u8 { + *b +} + +// CHECK-LABEL: ; sanitize_off::sanitized +// CHECK-NEXT: ; Function Attrs: +// CHECK: sanitize_address +// CHECK: start: +// CHECK: call void @__asan_report_load +// CHECK: } +pub fn sanitized(b: &mut u8) -> u8 { + *b +} + +#[sanitize(address = "off")] +pub mod foo { + // CHECK-LABEL: ; sanitize_off::foo::unsanitized + // CHECK-NEXT: ; Function Attrs: + // CHECK-NOT: sanitize_address + // CHECK: start: + // CHECK-NOT: call void @__asan_report_load + // CHECK: } + pub fn unsanitized(b: &mut u8) -> u8 { + *b + } + + // CHECK-LABEL: ; sanitize_off::foo::sanitized + // CHECK-NEXT: ; Function Attrs: + // CHECK: sanitize_address + // CHECK: start: + // CHECK: call void @__asan_report_load + // CHECK: } + #[sanitize(address = "on")] + pub fn sanitized(b: &mut u8) -> u8 { + *b + } +} + +pub trait MyTrait { + fn unsanitized(&self, b: &mut u8) -> u8; + fn sanitized(&self, b: &mut u8) -> u8; + + // CHECK-LABEL: ; sanitize_off::MyTrait::unsanitized_default + // CHECK-NEXT: ; Function Attrs: + // CHECK-NOT: sanitize_address + // CHECK: start: + // CHECK-NOT: call void @__asan_report_load + // CHECK: } + #[sanitize(address = "off")] + fn unsanitized_default(&self, b: &mut u8) -> u8 { + *b + } + + // CHECK-LABEL: ; sanitize_off::MyTrait::sanitized_default + // CHECK-NEXT: ; Function Attrs: + // CHECK: sanitize_address + // CHECK: start: + // CHECK: call void @__asan_report_load + // CHECK: } + fn sanitized_default(&self, b: &mut u8) -> u8 { + *b + } +} + +#[sanitize(address = "off")] +impl MyTrait for () { + // CHECK-LABEL: ; <() as sanitize_off::MyTrait>::unsanitized + // CHECK-NEXT: ; Function Attrs: + // CHECK-NOT: sanitize_address + // CHECK: start: + // CHECK-NOT: call void @__asan_report_load + // CHECK: } + fn unsanitized(&self, b: &mut u8) -> u8 { + *b + } + + // CHECK-LABEL: ; <() as sanitize_off::MyTrait>::sanitized + // CHECK-NEXT: ; Function Attrs: + // CHECK: sanitize_address + // CHECK: start: + // CHECK: call void @__asan_report_load + // CHECK: } + #[sanitize(address = "on")] + fn sanitized(&self, b: &mut u8) -> u8 { + *b + } +} + +pub fn expose_trait(b: &mut u8) -> u8 { + <() as MyTrait>::unsanitized_default(&(), b); + <() as MyTrait>::sanitized_default(&(), b) +} diff --git a/tests/codegen/sanitizer/scs-attr-check.rs b/tests/codegen/sanitizer/scs-attr-check.rs index 6f4cbc2c0a6bc..f726503503c96 100644 --- a/tests/codegen/sanitizer/scs-attr-check.rs +++ b/tests/codegen/sanitizer/scs-attr-check.rs @@ -5,7 +5,7 @@ //@ compile-flags: -Zsanitizer=shadow-call-stack #![crate_type = "lib"] -#![feature(no_sanitize)] +#![feature(sanitize)] // CHECK: ; sanitizer_scs_attr_check::scs // CHECK-NEXT: ; Function Attrs:{{.*}}shadowcallstack @@ -13,5 +13,5 @@ pub fn scs() {} // CHECK: ; sanitizer_scs_attr_check::no_scs // CHECK-NOT: ; Function Attrs:{{.*}}shadowcallstack -#[no_sanitize(shadow_call_stack)] +#[sanitize(shadow_call_stack = "off")] pub fn no_scs() {} diff --git a/tests/mir-opt/inline/inline_compatibility.rs b/tests/mir-opt/inline/inline_compatibility.rs index 1bb102ccda58a..a31153dedc9fe 100644 --- a/tests/mir-opt/inline/inline_compatibility.rs +++ b/tests/mir-opt/inline/inline_compatibility.rs @@ -3,7 +3,7 @@ //@ compile-flags: -Cpanic=abort #![crate_type = "lib"] -#![feature(no_sanitize)] +#![feature(sanitize)] #![feature(c_variadic)] #[inline] @@ -37,22 +37,22 @@ pub unsafe fn f2() { } #[inline] -#[no_sanitize(address)] -pub unsafe fn no_sanitize() {} +#[sanitize(address = "off")] +pub unsafe fn sanitize_off() {} -// CHECK-LABEL: fn inlined_no_sanitize() +// CHECK-LABEL: fn inlined_sanitize_off() // CHECK: bb0: { // CHECK-NEXT: return; -#[no_sanitize(address)] -pub unsafe fn inlined_no_sanitize() { - no_sanitize(); +#[sanitize(address = "off")] +pub unsafe fn inlined_sanitize_off() { + sanitize_off(); } -// CHECK-LABEL: fn not_inlined_no_sanitize() +// CHECK-LABEL: fn not_inlined_sanitize_off() // CHECK: bb0: { -// CHECK-NEXT: no_sanitize() -pub unsafe fn not_inlined_no_sanitize() { - no_sanitize(); +// CHECK-NEXT: sanitize_off() +pub unsafe fn not_inlined_sanitize_off() { + sanitize_off(); } // CHECK-LABEL: fn not_inlined_c_variadic() diff --git a/tests/ui/attributes/no-sanitize.rs b/tests/ui/attributes/no-sanitize.rs deleted file mode 100644 index ddf909be63a8a..0000000000000 --- a/tests/ui/attributes/no-sanitize.rs +++ /dev/null @@ -1,45 +0,0 @@ -#![feature(no_sanitize)] -#![feature(stmt_expr_attributes)] -#![deny(unused_attributes)] -#![allow(dead_code)] - -fn invalid() { - #[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function - { - 1 - }; -} - -#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function -type InvalidTy = (); - -#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function -mod invalid_module {} - -fn main() { - let _ = #[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function - (|| 1); -} - -#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function -struct F; - -#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function -impl F { - #[no_sanitize(memory)] - fn valid(&self) {} -} - -#[no_sanitize(address, memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function -static INVALID : i32 = 0; - -#[no_sanitize(memory)] -fn valid() {} - -#[no_sanitize(address)] -static VALID : i32 = 0; - -#[no_sanitize("address")] -//~^ ERROR `#[no_sanitize(...)]` should be applied to a function -//~| ERROR invalid argument for `no_sanitize` -static VALID2 : i32 = 0; diff --git a/tests/ui/attributes/no-sanitize.stderr b/tests/ui/attributes/no-sanitize.stderr deleted file mode 100644 index 8d5fbb109eadb..0000000000000 --- a/tests/ui/attributes/no-sanitize.stderr +++ /dev/null @@ -1,80 +0,0 @@ -error: `#[no_sanitize(memory)]` should be applied to a function - --> $DIR/no-sanitize.rs:7:19 - | -LL | #[no_sanitize(memory)] - | ^^^^^^ -LL | / { -LL | | 1 -LL | | }; - | |_____- not a function - -error: `#[no_sanitize(memory)]` should be applied to a function - --> $DIR/no-sanitize.rs:13:15 - | -LL | #[no_sanitize(memory)] - | ^^^^^^ -LL | type InvalidTy = (); - | -------------------- not a function - -error: `#[no_sanitize(memory)]` should be applied to a function - --> $DIR/no-sanitize.rs:16:15 - | -LL | #[no_sanitize(memory)] - | ^^^^^^ -LL | mod invalid_module {} - | --------------------- not a function - -error: `#[no_sanitize(memory)]` should be applied to a function - --> $DIR/no-sanitize.rs:20:27 - | -LL | let _ = #[no_sanitize(memory)] - | ^^^^^^ -LL | (|| 1); - | ------ not a function - -error: `#[no_sanitize(memory)]` should be applied to a function - --> $DIR/no-sanitize.rs:24:15 - | -LL | #[no_sanitize(memory)] - | ^^^^^^ -LL | struct F; - | --------- not a function - -error: `#[no_sanitize(memory)]` should be applied to a function - --> $DIR/no-sanitize.rs:27:15 - | -LL | #[no_sanitize(memory)] - | ^^^^^^ -LL | / impl F { -LL | | #[no_sanitize(memory)] -LL | | fn valid(&self) {} -LL | | } - | |_- not a function - -error: `#[no_sanitize(memory)]` should be applied to a function - --> $DIR/no-sanitize.rs:33:24 - | -LL | #[no_sanitize(address, memory)] - | ^^^^^^ -LL | static INVALID : i32 = 0; - | ------------------------- not a function - -error: `#[no_sanitize(...)]` should be applied to a function - --> $DIR/no-sanitize.rs:42:15 - | -LL | #[no_sanitize("address")] - | ^^^^^^^^^ -... -LL | static VALID2 : i32 = 0; - | ------------------------ not a function - -error: invalid argument for `no_sanitize` - --> $DIR/no-sanitize.rs:42:15 - | -LL | #[no_sanitize("address")] - | ^^^^^^^^^ - | - = note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread` - -error: aborting due to 9 previous errors - diff --git a/tests/ui/feature-gates/feature-gate-no_sanitize.rs b/tests/ui/feature-gates/feature-gate-no_sanitize.rs deleted file mode 100644 index 5ac014f1c5bf4..0000000000000 --- a/tests/ui/feature-gates/feature-gate-no_sanitize.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[no_sanitize(address)] -//~^ ERROR the `#[no_sanitize]` attribute is an experimental feature -fn main() { -} diff --git a/tests/ui/feature-gates/feature-gate-no_sanitize.stderr b/tests/ui/feature-gates/feature-gate-no_sanitize.stderr deleted file mode 100644 index a33bf6a9e40c1..0000000000000 --- a/tests/ui/feature-gates/feature-gate-no_sanitize.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: the `#[no_sanitize]` attribute is an experimental feature - --> $DIR/feature-gate-no_sanitize.rs:1:1 - | -LL | #[no_sanitize(address)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #39699 for more information - = help: add `#![feature(no_sanitize)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-sanitize.rs b/tests/ui/feature-gates/feature-gate-sanitize.rs new file mode 100644 index 0000000000000..40098d93272cb --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-sanitize.rs @@ -0,0 +1,7 @@ +//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION" +#![feature(no_sanitize)] //~ ERROR feature has been removed + +#[sanitize(address = "on")] +//~^ ERROR the `#[sanitize]` attribute is an experimental feature +fn main() { +} diff --git a/tests/ui/feature-gates/feature-gate-sanitize.stderr b/tests/ui/feature-gates/feature-gate-sanitize.stderr new file mode 100644 index 0000000000000..7740f55ab5c9b --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-sanitize.stderr @@ -0,0 +1,23 @@ +error[E0557]: feature has been removed + --> $DIR/feature-gate-sanitize.rs:2:12 + | +LL | #![feature(no_sanitize)] + | ^^^^^^^^^^^ feature has been removed + | + = note: removed in CURRENT_RUSTC_VERSION (you are using $RUSTC_VERSION); see for more information + = note: renamed to sanitize(xyz = "on|off") + +error[E0658]: the `#[sanitize]` attribute is an experimental feature + --> $DIR/feature-gate-sanitize.rs:4:1 + | +LL | #[sanitize(address = "on")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #39699 for more information + = help: add `#![feature(sanitize)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0557, E0658. +For more information about an error, try `rustc --explain E0557`. diff --git a/tests/ui/invalid/invalid-no-sanitize.rs b/tests/ui/invalid/invalid-no-sanitize.rs deleted file mode 100644 index b52e3cc83fab2..0000000000000 --- a/tests/ui/invalid/invalid-no-sanitize.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(no_sanitize)] - -#[no_sanitize(brontosaurus)] //~ ERROR invalid argument -fn main() { -} diff --git a/tests/ui/invalid/invalid-no-sanitize.stderr b/tests/ui/invalid/invalid-no-sanitize.stderr deleted file mode 100644 index b1c80438b318d..0000000000000 --- a/tests/ui/invalid/invalid-no-sanitize.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: invalid argument for `no_sanitize` - --> $DIR/invalid-no-sanitize.rs:3:15 - | -LL | #[no_sanitize(brontosaurus)] - | ^^^^^^^^^^^^ - | - = note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread` - -error: aborting due to 1 previous error - diff --git a/tests/ui/sanitize-attr/invalid-sanitize.rs b/tests/ui/sanitize-attr/invalid-sanitize.rs new file mode 100644 index 0000000000000..49dc01c8daaf4 --- /dev/null +++ b/tests/ui/sanitize-attr/invalid-sanitize.rs @@ -0,0 +1,22 @@ +#![feature(sanitize)] + +#[sanitize(brontosaurus = "off")] //~ ERROR invalid argument +fn main() { +} + +#[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes +#[sanitize(address = "off")] +fn multiple_consistent() {} + +#[sanitize(address = "on")] //~ ERROR multiple `sanitize` attributes +#[sanitize(address = "off")] +fn multiple_inconsistent() {} + +#[sanitize(address = "bogus")] //~ ERROR invalid argument for `sanitize` +fn wrong_value() {} + +#[sanitize = "off"] //~ ERROR malformed `sanitize` attribute input +fn name_value () {} + +#[sanitize] //~ ERROR malformed `sanitize` attribute input +fn just_word() {} diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr new file mode 100644 index 0000000000000..93c77ce1077cf --- /dev/null +++ b/tests/ui/sanitize-attr/invalid-sanitize.stderr @@ -0,0 +1,54 @@ +error: malformed `sanitize` attribute input + --> $DIR/invalid-sanitize.rs:18:1 + | +LL | #[sanitize = "off"] + | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[sanitize(address = "on|off", cfi = "on|off")]` + +error: malformed `sanitize` attribute input + --> $DIR/invalid-sanitize.rs:21:1 + | +LL | #[sanitize] + | ^^^^^^^^^^^ help: must be of the form: `#[sanitize(address = "on|off", cfi = "on|off")]` + +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 + diff --git a/tests/ui/sanitize-attr/valid-sanitize.rs b/tests/ui/sanitize-attr/valid-sanitize.rs new file mode 100644 index 0000000000000..ebe76fcba0442 --- /dev/null +++ b/tests/ui/sanitize-attr/valid-sanitize.rs @@ -0,0 +1,115 @@ +//! Tests where the `#[sanitize(..)]` attribute can and cannot be used. + +#![feature(sanitize)] +#![feature(extern_types)] +#![feature(impl_trait_in_assoc_type)] +#![warn(unused_attributes)] +#![sanitize(address = "off", thread = "on")] + +#[sanitize(address = "off", thread = "on")] +mod submod {} + +#[sanitize(address = "off")] +static FOO: u32 = 0; + +#[sanitize(thread = "off")] //~ ERROR sanitize attribute not allowed here +static BAR: u32 = 0; + +#[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here +type MyTypeAlias = (); + +#[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here +trait MyTrait { + #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + const TRAIT_ASSOC_CONST: u32; + + #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + type TraitAssocType; + + #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + fn trait_method(&self); + + #[sanitize(address = "off", thread = "on")] + fn trait_method_with_default(&self) {} + + #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + fn trait_assoc_fn(); +} + +#[sanitize(address = "off")] +impl MyTrait for () { + const TRAIT_ASSOC_CONST: u32 = 0; + + #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + type TraitAssocType = Self; + + #[sanitize(address = "off", thread = "on")] + fn trait_method(&self) {} + #[sanitize(address = "off", thread = "on")] + fn trait_method_with_default(&self) {} + #[sanitize(address = "off", thread = "on")] + fn trait_assoc_fn() {} +} + +trait HasAssocType { + type T; + fn constrain_assoc_type() -> Self::T; +} + +impl HasAssocType for () { + #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + type T = impl Copy; + fn constrain_assoc_type() -> Self::T {} +} + +#[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here +struct MyStruct { + #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + field: u32, +} + +#[sanitize(address = "off", thread = "on")] +impl MyStruct { + #[sanitize(address = "off", thread = "on")] + fn method(&self) {} + #[sanitize(address = "off", thread = "on")] + fn assoc_fn() {} +} + +extern "C" { + #[sanitize(address = "off", thread = "on")] //~ ERROR sanitize attribute not allowed here + static X: u32; + + #[sanitize(address = "off", thread = "on")] //~ ERROR sanitize attribute not allowed here + type T; + + #[sanitize(address = "off", thread = "on")] //~ ERROR sanitize attribute not allowed here + fn foreign_fn(); +} + +#[sanitize(address = "off", thread = "on")] +fn main() { + #[sanitize(address = "off", thread = "on")] //~ ERROR sanitize attribute not allowed here + let _ = (); + + // Currently not allowed on let statements, even if they bind to a closure. + // It might be nice to support this as a special case someday, but trying + // to define the precise boundaries of that special case might be tricky. + #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + let _let_closure = || (); + + // In situations where attributes can already be applied to expressions, + // the sanitize attribute is allowed on closure expressions. + let _closure_tail_expr = { + #[sanitize(address = "off", thread = "on")] + || () + }; + + match () { + #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + () => (), + } + + #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + return (); +} diff --git a/tests/ui/sanitize-attr/valid-sanitize.stderr b/tests/ui/sanitize-attr/valid-sanitize.stderr new file mode 100644 index 0000000000000..ff9fe63eaf558 --- /dev/null +++ b/tests/ui/sanitize-attr/valid-sanitize.stderr @@ -0,0 +1,190 @@ +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:15:1 + | +LL | #[sanitize(thread = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | static BAR: u32 = 0; + | -------------------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:18:1 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type MyTypeAlias = (); + | ---------------------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:21:1 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / trait MyTrait { +LL | | #[sanitize(address = "off")] +LL | | const TRAIT_ASSOC_CONST: u32; +... | +LL | | fn trait_assoc_fn(); +LL | | } + | |_- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:65:1 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / struct MyStruct { +LL | | #[sanitize(address = "off")] +LL | | field: u32, +LL | | } + | |_- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:67:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | field: u32, + | ---------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:92:5 + | +LL | #[sanitize(address = "off", thread = "on")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _ = (); + | ----------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:98:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _let_closure = || (); + | ------------------------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:109:9 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | () => (), + | -------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:113:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | return (); + | --------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:23:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const TRAIT_ASSOC_CONST: u32; + | ----------------------------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:26:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type TraitAssocType; + | -------------------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:29:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn trait_method(&self); + | ----------------------- function has no body + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:35:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn trait_assoc_fn(); + | -------------------- function has no body + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:43:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type TraitAssocType = Self; + | --------------------------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:60:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type T = impl Copy; + | ------------------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:80:5 + | +LL | #[sanitize(address = "off", thread = "on")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | static X: u32; + | -------------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:83:5 + | +LL | #[sanitize(address = "off", thread = "on")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type T; + | ------- not a function, impl block, or module + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: sanitize attribute not allowed here + --> $DIR/valid-sanitize.rs:86:5 + | +LL | #[sanitize(address = "off", thread = "on")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foreign_fn(); + | ---------------- function has no body + | + = help: sanitize attribute can be applied to a function (with body), impl block, or module + +error: aborting due to 18 previous errors + diff --git a/tests/ui/sanitizer/inline-always.rs b/tests/ui/sanitizer/inline-always-sanitize.rs similarity index 51% rename from tests/ui/sanitizer/inline-always.rs rename to tests/ui/sanitizer/inline-always-sanitize.rs index d92daee3026a6..2f1c8bb9c5bb0 100644 --- a/tests/ui/sanitizer/inline-always.rs +++ b/tests/ui/sanitizer/inline-always-sanitize.rs @@ -1,11 +1,11 @@ //@ check-pass -#![feature(no_sanitize)] +#![feature(sanitize)] #[inline(always)] //~^ NOTE inlining requested here -#[no_sanitize(address)] -//~^ WARN will have no effect after inlining +#[sanitize(address = "off")] +//~^ WARN setting `sanitize` off will have no effect after inlining //~| NOTE on by default fn x() { } diff --git a/tests/ui/sanitizer/inline-always-sanitize.stderr b/tests/ui/sanitizer/inline-always-sanitize.stderr new file mode 100644 index 0000000000000..ed47947216950 --- /dev/null +++ b/tests/ui/sanitizer/inline-always-sanitize.stderr @@ -0,0 +1,15 @@ +warning: setting `sanitize` off will have no effect after inlining + --> $DIR/inline-always-sanitize.rs:7:1 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: inlining requested here + --> $DIR/inline-always-sanitize.rs:5:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + = note: `#[warn(inline_no_sanitize)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/sanitizer/inline-always.stderr b/tests/ui/sanitizer/inline-always.stderr deleted file mode 100644 index 74fba3c0e0e59..0000000000000 --- a/tests/ui/sanitizer/inline-always.stderr +++ /dev/null @@ -1,15 +0,0 @@ -warning: `no_sanitize` will have no effect after inlining - --> $DIR/inline-always.rs:7:1 - | -LL | #[no_sanitize(address)] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | -note: inlining requested here - --> $DIR/inline-always.rs:5:1 - | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ - = note: `#[warn(inline_no_sanitize)]` on by default - -warning: 1 warning emitted - diff --git a/triagebot.toml b/triagebot.toml index e5af77b6d443f..4b94811315867 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -545,7 +545,7 @@ trigger_files = [ "src/doc/unstable-book/src/compiler-flags/sanitizer.md", "src/doc/unstable-book/src/language-features/cfg-sanitize.md", "src/doc/unstable-book/src/language-features/cfi-encoding.md", - "src/doc/unstable-book/src/language-features/no-sanitize.md", + "src/doc/unstable-book/src/language-features/sanitize.md", "tests/codegen/sanitizer", "tests/codegen/split-lto-unit.rs", "tests/codegen/stack-probes-inline.rs", @@ -1098,7 +1098,7 @@ cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] [mentions."src/doc/unstable-book/src/language-features/cfi-encoding.md"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] -[mentions."src/doc/unstable-book/src/language-features/no-sanitize.md"] +[mentions."src/doc/unstable-book/src/language-features/sanitize.md"] cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] [mentions."src/doc/rustc/src/check-cfg.md"]