Skip to content

Remove the #[no_sanitize] attribute in favor of #[sanitize(xyz = "on|off")] #142681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
133 changes: 94 additions & 39 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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[..] {
Expand Down Expand Up @@ -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| {
Expand Down Expand Up @@ -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");
})
}
Expand Down Expand Up @@ -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::<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 {
// 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(
Expand Down Expand Up @@ -900,5 +950,10 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
}

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
};
}
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]),
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>` binders in where-clauses
Expand Down Expand Up @@ -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).
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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! {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ pub struct CodegenFnAttrs {
/// The `#[link_section = "..."]` attribute, or what executable section this
/// should be placed in.
pub link_section: Option<Symbol>,
/// 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
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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! }
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 ->
Expand Down
Loading
Loading