Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
aab1563
`impl PartialEq<{str,String}> for {Path,PathBuf}`
Kixunil Dec 18, 2022
964eb82
Stabilize `ip_from`
GrigorenkoPV May 29, 2025
06ae1be
Make doc for transpose api better
chenyukang Jun 22, 2025
a067c6a
refactor `unreachable/expr_cast.rs` test
WaffleLapkin Jun 1, 2025
d2e133d
don't warn on explicit casts of never to any
WaffleLapkin Jun 1, 2025
3a993a6
Ignore sleep_until test on SGX
raoulstrackx Aug 5, 2025
4e2d420
avoid duplicate error string
lcnr Aug 7, 2025
d62e857
also consider HR bounds
lcnr Aug 7, 2025
a95a2ac
rework `add_placeholder_from_predicate_note`
lcnr Aug 7, 2025
5c716bd
add comment
lcnr Aug 7, 2025
3ebf611
it's not a borrow checker limitation :<
lcnr Aug 13, 2025
8d0a049
Declare module `rustc_codegen_llvm::back` in the normal way
Zalathar Aug 15, 2025
44f5ec7
Avoid an explicit cast from `*const c_uchar` to `*const c_char`
Zalathar Aug 15, 2025
61932e1
Avoid an unnecessary intermediate `&mut` reference
Zalathar Aug 15, 2025
9e7d066
Simplify the `args_cstr_buff` assertion
Zalathar Aug 15, 2025
8511e40
rustdoc-search: search backend with partitioned suffix tree
notriddle Nov 22, 2024
cf8ec67
Remove `LlvmArchiveBuilder` and supporting code/bindings
Zalathar Aug 16, 2025
ddf39ca
Avoid copying rustc rmeta artifacts into the build compiler sysroot
Kobzol Aug 16, 2025
70e26c1
take attr style into account in attr diagnostics
jdonszelmann Aug 11, 2025
814b8e6
Only check std in cross-compilation instead of building it
Kobzol Aug 16, 2025
4335405
overhaul `&mut` suggestions in borrowck errors
fee1-dead Aug 6, 2025
e78b417
refactor return type of `suggest_ampmut` into an enum
fee1-dead Aug 16, 2025
3ef065b
Implement the #[sanitize(..)] attribute
1c3t3a Jun 18, 2025
95bdb34
Remove the no_sanitize attribute in favor of sanitize
1c3t3a Jun 18, 2025
22519d3
Do not overwrite the value of `RUSTC_ADDITIONAL_SYSROOT_PATHS`
Kobzol Aug 18, 2025
4668751
Print what bootstrap invocation failed when an error happens in CI
Kobzol Aug 18, 2025
a1f5bbe
Provide more useful command creation spans
Kobzol Aug 18, 2025
a6a760e
Remove the `From` derive macro from prelude
Kobzol Aug 18, 2025
c6db6f2
comment style changes
fee1-dead Aug 18, 2025
79a40c9
rustdoc: add rustdoc top bar web component
notriddle Aug 18, 2025
704cb8f
interpret: avoid forcing all integer newtypes into memory during clea…
RalfJung Aug 18, 2025
79d3006
cleanup: make run-make test use run_in_tmpdir
durin42 Aug 14, 2025
9d08596
tests: fix RISC-V failures and adjust transmute-scalar.rs target
Jul 28, 2025
4c21251
Fix uplifting in `Assemble` step
Kobzol Aug 18, 2025
533ecdb
Assume UTF-8 in sysroot paths
Kobzol Aug 18, 2025
2beb54c
Rollup merge of #140956 - Kixunil:impl-partialeq-str-for-path, r=Amanieu
Zalathar Aug 19, 2025
027c7a5
Rollup merge of #141744 - GrigorenkoPV:ip_from, r=Amanieu
Zalathar Aug 19, 2025
633cc0c
Rollup merge of #142681 - 1c3t3a:sanitize-off-on, r=rcvalle
Zalathar Aug 19, 2025
0671b2f
Rollup merge of #142871 - chenyukang:yukang-fix-doc-for-transpose, r=…
Zalathar Aug 19, 2025
b9fdc6b
Rollup merge of #144252 - Kobzol:rmeta-sysroot, r=jieyouxu
Zalathar Aug 19, 2025
d6645f7
Rollup merge of #144476 - notriddle:notriddle/stringdex, r=lolbinaryc…
Zalathar Aug 19, 2025
3a03bb9
Rollup merge of #144567 - CaiWeiran:transmute-scalar_test, r=nikic
Zalathar Aug 19, 2025
cff7ed1
Rollup merge of #144804 - WaffleLapkin:reach-for-the-casts, r=compile…
Zalathar Aug 19, 2025
d0fa5c7
Rollup merge of #144960 - raoulstrackx:raoul/rte-513-disable_sleep_te…
Zalathar Aug 19, 2025
181480d
Rollup merge of #145013 - fee1-dead-contrib:push-vwvsqsqnrxqm, r=nnet…
Zalathar Aug 19, 2025
f3f1847
Rollup merge of #145041 - lcnr:borrowck-limitations-error, r=BoxyUwU
Zalathar Aug 19, 2025
11c6d89
Rollup merge of #145243 - jdonszelmann:inner-attr-errors, r=petrochenkov
Zalathar Aug 19, 2025
02848e7
Rollup merge of #145405 - durin42:test-cleanup-tmpdir, r=lqd
Zalathar Aug 19, 2025
8945924
Rollup merge of #145432 - Zalathar:target-machine, r=wesleywiser
Zalathar Aug 19, 2025
8748d8e
Rollup merge of #145484 - Zalathar:archive-builder, r=bjorn3
Zalathar Aug 19, 2025
cf2f50e
Rollup merge of #145557 - Kobzol:rustc-link-fix, r=jieyouxu
Zalathar Aug 19, 2025
f44f963
Rollup merge of #145563 - Kobzol:remove-from-from-prelude, r=petroche…
Zalathar Aug 19, 2025
3ced940
Rollup merge of #145565 - Kobzol:bootstrap-ci-print-error, r=jieyouxu
Zalathar Aug 19, 2025
531ec85
Rollup merge of #145584 - RalfJung:interpret-clear-provenance, r=comp…
Zalathar Aug 19, 2025
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
Prev Previous commit
Next Next commit
Implement the #[sanitize(..)] attribute
This change implements the #[sanitize(..)] attribute, which opts to
replace the currently unstable #[no_sanitize]. Essentially the new
attribute works similar as #[no_sanitize], just with more flexible
options regarding where it is applied. E.g. it is possible to turn
a certain sanitizer either on or off:
`#[sanitize(address = "on|off")]`

This attribute now also applies to more places, e.g. it is possible
to turn off a sanitizer for an entire module or impl block:
```rust
\#[sanitize(address = "off")]
mod foo {
    fn unsanitized(..) {}

    #[sanitize(address = "on")]
    fn sanitized(..) {}
}

\#[sanitize(thread = "off")]
impl MyTrait for () {
    ...
}
```

This attribute is enabled behind the unstable `sanitize` feature.
  • Loading branch information
1c3t3a committed Aug 18, 2025
commit 3ef065bf872ce62a18336dca0daf47b3e9f7da64
3 changes: 3 additions & 0 deletions compiler/rustc_codegen_ssa/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomo
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`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`

codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed

codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
Expand Down
102 changes: 100 additions & 2 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ fn parse_patchable_function_entry(
struct InterestingAttributeDiagnosticSpans {
link_ordinal: Option<Span>,
no_sanitize: Option<Span>,
sanitize: Option<Span>,
inline: Option<Span>,
no_mangle: Option<Span>,
}
Expand Down Expand Up @@ -335,6 +336,7 @@ fn process_builtin_attrs(
codegen_fn_attrs.no_sanitize |=
parse_no_sanitize_attr(tcx, attr).unwrap_or_default();
}
sym::sanitize => interesting_spans.sanitize = Some(attr.span()),
sym::instruction_set => {
codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr)
}
Expand All @@ -358,6 +360,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
codegen_fn_attrs.alignment =
Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment);

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

Expand Down Expand Up @@ -463,6 +467,17 @@ fn check_result(
lint.span_note(inline_span, "inlining requested here");
})
}
if !codegen_fn_attrs.no_sanitize.is_empty()
&& codegen_fn_attrs.inline.always()
&& let (Some(sanitize_span), Some(inline_span)) =
(interesting_spans.sanitize, interesting_spans.inline)
{
let hir_id = tcx.local_def_id_to_hir_id(did);
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");
})
}

// error when specifying link_name together with link_ordinal
if let Some(_) = codegen_fn_attrs.link_name
Expand Down Expand Up @@ -585,6 +600,84 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
}
}

/// For an attr that has the `sanitize` attribute, read the list of
/// disabled sanitizers.
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() {
[sym::address] if set.value_str() == Some(sym::off) => {
result |= SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
}
[sym::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(),
}
}

/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
/// applied to the method prototype.
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
Expand Down Expand Up @@ -709,6 +802,11 @@ pub 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, inherited_align, ..*providers };
*providers = Providers {
codegen_fn_attrs,
should_inherit_track_caller,
inherited_align,
disabled_sanitizers_for,
..*providers
};
}
8 changes: 8 additions & 0 deletions compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,14 @@ pub(crate) struct InvalidNoSanitize {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(codegen_ssa_invalid_sanitize)]
#[note]
pub(crate) struct InvalidSanitize {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(codegen_ssa_target_feature_safe_trait)]
pub(crate) struct TargetFeatureSafeTrait {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
template!(List: &["address, kcfi, memory, thread"]), DuplicatesOk,
EncodeCrossCrate::No, experimental!(no_sanitize)
),
gated!(
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,
EncodeCrossCrate::No, sanitize, experimental!(sanitize),
),
gated!(
coverage, Normal, template!(OneOf: &[sym::off, sym::on]),
ErrorPreceding, EncodeCrossCrate::No,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,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
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 @@ -343,6 +343,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 @@ -100,7 +100,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_hir as hir};

use crate::infer::canonical::{self, Canonical};
Expand Down Expand Up @@ -2686,6 +2686,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
6 changes: 6 additions & 0 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,12 @@ passes_rustc_pub_transparent =
attribute should be applied to `#[repr(transparent)]` types
.label = not a `#[repr(transparent)]` type

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
44 changes: 43 additions & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::no_sanitize, ..] => {
self.check_no_sanitize(attr, span, target)
}
[sym::sanitize, ..] => {
self.check_sanitize(attr, span, target)
}
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
[sym::doc, ..] => self.check_doc_attrs(
attr,
Expand Down Expand Up @@ -518,6 +521,46 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}

/// Checks that the `#[sanitize(..)]` attribute is applied to a
/// function/closure/method, or to an impl block or module.
fn check_sanitize(&self, attr: &Attribute, target_span: Span, target: Target) {
let mut not_fn_impl_mod = None;
let mut no_body = None;

if let Some(list) = attr.meta_item_list() {
for item in list.iter() {
let MetaItemInner::MetaItem(set) = item else {
return;
};
let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
match target {
Target::Fn
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
| Target::Impl { .. }
| Target::Mod => return,
Target::Static if matches!(segments.as_slice(), [sym::address]) => return,

// These are "functions", but they aren't allowed because they don't
// have a body, so the usual explanation would be confusing.
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
no_body = Some(target_span);
}

_ => {
not_fn_impl_mod = Some(target_span);
}
}
}
self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
attr_span: attr.span(),
not_fn_impl_mod,
no_body,
help: (),
});
}
}

/// Checks if `#[naked]` is applied to a function definition.
fn check_naked(&self, hir_id: HirId, target: Target) {
match target {
Expand Down Expand Up @@ -561,7 +604,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
}

/// Checks if `#[collapse_debuginfo]` is applied to a macro.
fn check_collapse_debuginfo(&self, attr: &Attribute, span: Span, target: Target) {
match target {
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1499,6 +1499,23 @@ pub(crate) struct NoSanitize<'a> {
pub attr_str: &'a str,
}

/// "sanitize attribute not allowed here"
#[derive(Diagnostic)]
#[diag(passes_sanitize_attribute_not_allowed)]
pub(crate) struct SanitizeAttributeNotAllowed {
#[primary_span]
pub attr_span: Span,
/// "not a function, impl block, or module"
#[label(passes_not_fn_impl_mod)]
pub not_fn_impl_mod: Option<Span>,
/// "function has no body"
#[label(passes_no_body)]
pub no_body: Option<Span>,
/// "sanitize attribute can be applied to a function (with body), impl block, or module"
#[help]
pub help: (),
}

// FIXME(jdonszelmann): move back to rustc_attr
#[derive(Diagnostic)]
#[diag(passes_rustc_const_stable_indirect_pairing)]
Expand Down
Loading