Skip to content

Commit e6aa5b3

Browse files
authored
Unrolled build for #142681
Rollup merge of #142681 - 1c3t3a:sanitize-off-on, r=rcvalle Remove the `#[no_sanitize]` attribute in favor of `#[sanitize(xyz = "on|off")]` This came up during the sanitizer stabilization (#123617). Instead of a `#[no_sanitize(xyz)]` attribute, we would like to have a `#[sanitize(xyz = "on|off")]` attribute, which is more powerful and allows to be extended in the future (instead of just focusing on turning sanitizers off). The implementation is done according to what was [discussed on Zulip](https://rust-lang.zulipchat.com/#narrow/channel/343119-project-exploit-mitigations/topic/Stabilize.20the.20.60no_sanitize.60.20attribute/with/495377292)). The new attribute also works on modules, traits and impl items and thus enables usage as the following: ```rust #[sanitize(address = "off")] mod foo { fn unsanitized(..) {} #[sanitize(address = "on")] fn sanitized(..) {} } trait MyTrait { #[sanitize(address = "off")] fn unsanitized_default(..) {} } #[sanitize(thread = "off")] impl MyTrait for () { ... } ``` r? ```@rcvalle```
2 parents b96868f + 95bdb34 commit e6aa5b3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+942
-345
lines changed

compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphizati
171171
172172
codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
173173
174-
codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize`
175-
.note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
174+
codegen_ssa_invalid_sanitize = invalid argument for `sanitize`
175+
.note = expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
176176
177177
codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
178178

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 100 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -77,32 +77,6 @@ fn parse_instruction_set_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<Instr
7777
}
7878
}
7979

80-
// FIXME(jdonszelmann): remove when no_sanitize becomes a parsed attr
81-
fn parse_no_sanitize_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<SanitizerSet> {
82-
let list = attr.meta_item_list()?;
83-
let mut sanitizer_set = SanitizerSet::empty();
84-
85-
for item in list.iter() {
86-
match item.name() {
87-
Some(sym::address) => {
88-
sanitizer_set |= SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
89-
}
90-
Some(sym::cfi) => sanitizer_set |= SanitizerSet::CFI,
91-
Some(sym::kcfi) => sanitizer_set |= SanitizerSet::KCFI,
92-
Some(sym::memory) => sanitizer_set |= SanitizerSet::MEMORY,
93-
Some(sym::memtag) => sanitizer_set |= SanitizerSet::MEMTAG,
94-
Some(sym::shadow_call_stack) => sanitizer_set |= SanitizerSet::SHADOWCALLSTACK,
95-
Some(sym::thread) => sanitizer_set |= SanitizerSet::THREAD,
96-
Some(sym::hwaddress) => sanitizer_set |= SanitizerSet::HWADDRESS,
97-
_ => {
98-
tcx.dcx().emit_err(errors::InvalidNoSanitize { span: item.span() });
99-
}
100-
}
101-
}
102-
103-
Some(sanitizer_set)
104-
}
105-
10680
// FIXME(jdonszelmann): remove when patchable_function_entry becomes a parsed attr
10781
fn parse_patchable_function_entry(
10882
tcx: TyCtxt<'_>,
@@ -161,7 +135,7 @@ fn parse_patchable_function_entry(
161135
#[derive(Default)]
162136
struct InterestingAttributeDiagnosticSpans {
163137
link_ordinal: Option<Span>,
164-
no_sanitize: Option<Span>,
138+
sanitize: Option<Span>,
165139
inline: Option<Span>,
166140
no_mangle: Option<Span>,
167141
}
@@ -330,11 +304,7 @@ fn process_builtin_attrs(
330304
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
331305
}
332306
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
333-
sym::no_sanitize => {
334-
interesting_spans.no_sanitize = Some(attr.span());
335-
codegen_fn_attrs.no_sanitize |=
336-
parse_no_sanitize_attr(tcx, attr).unwrap_or_default();
337-
}
307+
sym::sanitize => interesting_spans.sanitize = Some(attr.span()),
338308
sym::instruction_set => {
339309
codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr)
340310
}
@@ -358,6 +328,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
358328
codegen_fn_attrs.alignment =
359329
Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment);
360330

331+
// Compute the disabled sanitizers.
332+
codegen_fn_attrs.no_sanitize |= tcx.disabled_sanitizers_for(did);
361333
// On trait methods, inherit the `#[align]` of the trait's method prototype.
362334
codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.inherited_align(did));
363335

@@ -455,11 +427,11 @@ fn check_result(
455427
if !codegen_fn_attrs.no_sanitize.is_empty()
456428
&& codegen_fn_attrs.inline.always()
457429
&& let (Some(no_sanitize_span), Some(inline_span)) =
458-
(interesting_spans.no_sanitize, interesting_spans.inline)
430+
(interesting_spans.sanitize, interesting_spans.inline)
459431
{
460432
let hir_id = tcx.local_def_id_to_hir_id(did);
461433
tcx.node_span_lint(lint::builtin::INLINE_NO_SANITIZE, hir_id, no_sanitize_span, |lint| {
462-
lint.primary_message("`no_sanitize` will have no effect after inlining");
434+
lint.primary_message("setting `sanitize` off will have no effect after inlining");
463435
lint.span_note(inline_span, "inlining requested here");
464436
})
465437
}
@@ -585,6 +557,93 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
585557
}
586558
}
587559

560+
/// For an attr that has the `sanitize` attribute, read the list of
561+
/// disabled sanitizers. `current_attr` holds the information about
562+
/// previously parsed attributes.
563+
fn parse_sanitize_attr(
564+
tcx: TyCtxt<'_>,
565+
attr: &Attribute,
566+
current_attr: SanitizerSet,
567+
) -> SanitizerSet {
568+
let mut result = current_attr;
569+
if let Some(list) = attr.meta_item_list() {
570+
for item in list.iter() {
571+
let MetaItemInner::MetaItem(set) = item else {
572+
tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
573+
break;
574+
};
575+
let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
576+
match segments.as_slice() {
577+
// Similar to clang, sanitize(address = ..) and
578+
// sanitize(kernel_address = ..) control both ASan and KASan
579+
// Source: https://reviews.llvm.org/D44981.
580+
[sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::off) => {
581+
result |= SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
582+
}
583+
[sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::on) => {
584+
result &= !SanitizerSet::ADDRESS;
585+
result &= !SanitizerSet::KERNELADDRESS;
586+
}
587+
[sym::cfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::CFI,
588+
[sym::cfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::CFI,
589+
[sym::kcfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::KCFI,
590+
[sym::kcfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::KCFI,
591+
[sym::memory] if set.value_str() == Some(sym::off) => {
592+
result |= SanitizerSet::MEMORY
593+
}
594+
[sym::memory] if set.value_str() == Some(sym::on) => {
595+
result &= !SanitizerSet::MEMORY
596+
}
597+
[sym::memtag] if set.value_str() == Some(sym::off) => {
598+
result |= SanitizerSet::MEMTAG
599+
}
600+
[sym::memtag] if set.value_str() == Some(sym::on) => {
601+
result &= !SanitizerSet::MEMTAG
602+
}
603+
[sym::shadow_call_stack] if set.value_str() == Some(sym::off) => {
604+
result |= SanitizerSet::SHADOWCALLSTACK
605+
}
606+
[sym::shadow_call_stack] if set.value_str() == Some(sym::on) => {
607+
result &= !SanitizerSet::SHADOWCALLSTACK
608+
}
609+
[sym::thread] if set.value_str() == Some(sym::off) => {
610+
result |= SanitizerSet::THREAD
611+
}
612+
[sym::thread] if set.value_str() == Some(sym::on) => {
613+
result &= !SanitizerSet::THREAD
614+
}
615+
[sym::hwaddress] if set.value_str() == Some(sym::off) => {
616+
result |= SanitizerSet::HWADDRESS
617+
}
618+
[sym::hwaddress] if set.value_str() == Some(sym::on) => {
619+
result &= !SanitizerSet::HWADDRESS
620+
}
621+
_ => {
622+
tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
623+
}
624+
}
625+
}
626+
}
627+
result
628+
}
629+
630+
fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
631+
// Backtrack to the crate root.
632+
let disabled = match tcx.opt_local_parent(did) {
633+
// Check the parent (recursively).
634+
Some(parent) => tcx.disabled_sanitizers_for(parent),
635+
// We reached the crate root without seeing an attribute, so
636+
// there is no sanitizers to exclude.
637+
None => SanitizerSet::empty(),
638+
};
639+
640+
// Check for a sanitize annotation directly on this def.
641+
if let Some(attr) = tcx.get_attr(did, sym::sanitize) {
642+
return parse_sanitize_attr(tcx, attr, disabled);
643+
}
644+
disabled
645+
}
646+
588647
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
589648
/// applied to the method prototype.
590649
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
@@ -709,6 +768,11 @@ pub fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
709768
}
710769

711770
pub(crate) fn provide(providers: &mut Providers) {
712-
*providers =
713-
Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..*providers };
771+
*providers = Providers {
772+
codegen_fn_attrs,
773+
should_inherit_track_caller,
774+
inherited_align,
775+
disabled_sanitizers_for,
776+
..*providers
777+
};
714778
}

compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,9 +1121,9 @@ impl IntoDiagArg for ExpectedPointerMutability {
11211121
}
11221122

11231123
#[derive(Diagnostic)]
1124-
#[diag(codegen_ssa_invalid_no_sanitize)]
1124+
#[diag(codegen_ssa_invalid_sanitize)]
11251125
#[note]
1126-
pub(crate) struct InvalidNoSanitize {
1126+
pub(crate) struct InvalidSanitize {
11271127
#[primary_span]
11281128
pub span: Span,
11291129
}

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -741,9 +741,8 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
741741
ErrorPreceding, EncodeCrossCrate::No
742742
),
743743
gated!(
744-
no_sanitize, Normal,
745-
template!(List: &["address, kcfi, memory, thread"]), DuplicatesOk,
746-
EncodeCrossCrate::No, experimental!(no_sanitize)
744+
sanitize, Normal, 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""#]), ErrorPreceding,
745+
EncodeCrossCrate::No, sanitize, experimental!(sanitize),
747746
),
748747
gated!(
749748
coverage, Normal, template!(OneOf: &[sym::off, sym::on]),

compiler/rustc_feature/src/removed.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ declare_features! (
190190
(removed, no_coverage, "1.74.0", Some(84605), Some("renamed to `coverage_attribute`"), 114656),
191191
/// Allows `#[no_debug]`.
192192
(removed, no_debug, "1.43.0", Some(29721), Some("removed due to lack of demand"), 69667),
193+
// Allows the use of `no_sanitize` attribute.
194+
/// The feature was renamed to `sanitize` and the attribute to `#[sanitize(xyz = "on|off")]`
195+
(removed, no_sanitize, "CURRENT_RUSTC_VERSION", Some(39699), Some(r#"renamed to sanitize(xyz = "on|off")"#), 142681),
193196
/// Note: this feature was previously recorded in a separate
194197
/// `STABLE_REMOVED` list because it, uniquely, was once stable but was
195198
/// then removed. But there was no utility storing it separately, so now

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,8 +594,6 @@ declare_features! (
594594
(unstable, new_range, "1.86.0", Some(123741)),
595595
/// Allows `#![no_core]`.
596596
(unstable, no_core, "1.3.0", Some(29639)),
597-
/// Allows the use of `no_sanitize` attribute.
598-
(unstable, no_sanitize, "1.42.0", Some(39699)),
599597
/// Allows using the `non_exhaustive_omitted_patterns` lint.
600598
(unstable, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554)),
601599
/// Allows `for<T>` binders in where-clauses
@@ -628,6 +626,8 @@ declare_features! (
628626
(unstable, return_type_notation, "1.70.0", Some(109417)),
629627
/// Allows `extern "rust-cold"`.
630628
(unstable, rust_cold_cc, "1.63.0", Some(97544)),
629+
/// Allows the use of the `sanitize` attribute.
630+
(unstable, sanitize, "CURRENT_RUSTC_VERSION", Some(39699)),
631631
/// Allows the use of SIMD types in functions declared in `extern` blocks.
632632
(unstable, simd_ffi, "1.0.0", Some(27731)),
633633
/// Allows specialization of implementations (RFC 1210).

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,18 +2301,18 @@ declare_lint! {
23012301

23022302
declare_lint! {
23032303
/// The `inline_no_sanitize` lint detects incompatible use of
2304-
/// [`#[inline(always)]`][inline] and [`#[no_sanitize(...)]`][no_sanitize].
2304+
/// [`#[inline(always)]`][inline] and [`#[sanitize(xyz = "off")]`][sanitize].
23052305
///
23062306
/// [inline]: https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute
2307-
/// [no_sanitize]: https://doc.rust-lang.org/nightly/unstable-book/language-features/no-sanitize.html
2307+
/// [sanitize]: https://doc.rust-lang.org/nightly/unstable-book/language-features/no-sanitize.html
23082308
///
23092309
/// ### Example
23102310
///
23112311
/// ```rust
2312-
/// #![feature(no_sanitize)]
2312+
/// #![feature(sanitize)]
23132313
///
23142314
/// #[inline(always)]
2315-
/// #[no_sanitize(address)]
2315+
/// #[sanitize(address = "off")]
23162316
/// fn x() {}
23172317
///
23182318
/// fn main() {
@@ -2325,11 +2325,11 @@ declare_lint! {
23252325
/// ### Explanation
23262326
///
23272327
/// The use of the [`#[inline(always)]`][inline] attribute prevents the
2328-
/// the [`#[no_sanitize(...)]`][no_sanitize] attribute from working.
2328+
/// the [`#[sanitize(xyz = "off")]`][sanitize] attribute from working.
23292329
/// Consider temporarily removing `inline` attribute.
23302330
pub INLINE_NO_SANITIZE,
23312331
Warn,
2332-
"detects incompatible use of `#[inline(always)]` and `#[no_sanitize(...)]`",
2332+
r#"detects incompatible use of `#[inline(always)]` and `#[sanitize(... = "off")]`"#,
23332333
}
23342334

23352335
declare_lint! {

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ pub struct CodegenFnAttrs {
6161
/// The `#[link_section = "..."]` attribute, or what executable section this
6262
/// should be placed in.
6363
pub link_section: Option<Symbol>,
64-
/// The `#[no_sanitize(...)]` attribute. Indicates sanitizers for which
65-
/// instrumentation should be disabled inside the annotated function.
64+
/// The `#[sanitize(xyz = "off")]` attribute. Indicates sanitizers for which
65+
/// instrumentation should be disabled inside the function.
6666
pub no_sanitize: SanitizerSet,
6767
/// The `#[instruction_set(set)]` attribute. Indicates if the generated code should
6868
/// be generated against a specific instruction set. Only usable on architectures which allow

compiler/rustc_middle/src/query/erase.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ trivial! {
343343
rustc_span::Symbol,
344344
rustc_span::Ident,
345345
rustc_target::spec::PanicStrategy,
346+
rustc_target::spec::SanitizerSet,
346347
rustc_type_ir::Variance,
347348
u32,
348349
usize,

compiler/rustc_middle/src/query/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ use rustc_session::lint::LintExpectationId;
100100
use rustc_span::def_id::LOCAL_CRATE;
101101
use rustc_span::source_map::Spanned;
102102
use rustc_span::{DUMMY_SP, Span, Symbol};
103-
use rustc_target::spec::PanicStrategy;
103+
use rustc_target::spec::{PanicStrategy, SanitizerSet};
104104
use {rustc_abi as abi, rustc_ast as ast, rustc_hir as hir};
105105

106106
use crate::infer::canonical::{self, Canonical};
@@ -2686,6 +2686,16 @@ rustc_queries! {
26862686
desc { |tcx| "looking up anon const kind of `{}`", tcx.def_path_str(def_id) }
26872687
separate_provide_extern
26882688
}
2689+
2690+
/// Checks for the nearest `#[sanitize(xyz = "off")]` or
2691+
/// `#[sanitize(xyz = "on")]` on this def and any enclosing defs, up to the
2692+
/// crate root.
2693+
///
2694+
/// Returns the set of sanitizers that is explicitly disabled for this def.
2695+
query disabled_sanitizers_for(key: LocalDefId) -> SanitizerSet {
2696+
desc { |tcx| "checking what set of sanitizers are enabled on `{}`", tcx.def_path_str(key) }
2697+
feedable
2698+
}
26892699
}
26902700

26912701
rustc_with_all_queries! { define_callbacks! }

0 commit comments

Comments
 (0)