@@ -162,6 +162,7 @@ fn parse_patchable_function_entry(
162162struct InterestingAttributeDiagnosticSpans {
163163 link_ordinal : Option < Span > ,
164164 no_sanitize : Option < Span > ,
165+ sanitize : Option < Span > ,
165166 inline : Option < Span > ,
166167 no_mangle : Option < Span > ,
167168}
@@ -343,6 +344,7 @@ fn process_builtin_attrs(
343344 codegen_fn_attrs. no_sanitize |=
344345 parse_no_sanitize_attr ( tcx, attr) . unwrap_or_default ( ) ;
345346 }
347+ sym:: sanitize => interesting_spans. sanitize = Some ( attr. span ( ) ) ,
346348 sym:: instruction_set => {
347349 codegen_fn_attrs. instruction_set = parse_instruction_set_attr ( tcx, attr)
348350 }
@@ -366,6 +368,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
366368 codegen_fn_attrs. alignment =
367369 Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
368370
371+ // Compute the disabled sanitizers.
372+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
369373 // On trait methods, inherit the `#[align]` of the trait's method prototype.
370374 codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
371375
@@ -471,6 +475,16 @@ fn check_result(
471475 lint. span_note ( inline_span, "inlining requested here" ) ;
472476 } )
473477 }
478+ if !codegen_fn_attrs. no_sanitize . is_empty ( )
479+ && codegen_fn_attrs. inline . always ( )
480+ && let ( Some ( sanitize_span) , Some ( inline_span) ) = ( interesting_spans. sanitize , interesting_spans. inline )
481+ {
482+ let hir_id = tcx. local_def_id_to_hir_id ( did) ;
483+ tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, sanitize_span, |lint| {
484+ lint. primary_message ( "setting `sanitize` off will have no effect after inlining" ) ;
485+ lint. span_note ( inline_span, "inlining requested here" ) ;
486+ } )
487+ }
474488
475489 // error when specifying link_name together with link_ordinal
476490 if let Some ( _) = codegen_fn_attrs. link_name
@@ -593,6 +607,84 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
593607 }
594608}
595609
610+ /// For an attr that has the `sanitize` attribute, read the list of
611+ /// disabled sanitizers.
612+ fn parse_sanitize_attr ( tcx : TyCtxt < ' _ > , attr : & Attribute ) -> SanitizerSet {
613+ let mut result = SanitizerSet :: empty ( ) ;
614+ if let Some ( list) = attr. meta_item_list ( ) {
615+ for item in list. iter ( ) {
616+ let MetaItemInner :: MetaItem ( set) = item else {
617+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
618+ break ;
619+ } ;
620+ let segments = set. path . segments . iter ( ) . map ( |x| x. ident . name ) . collect :: < Vec < _ > > ( ) ;
621+ match segments. as_slice ( ) {
622+ [ sym:: address] if set. value_str ( ) == Some ( sym:: off) => {
623+ result |= SanitizerSet :: ADDRESS | SanitizerSet :: KERNELADDRESS
624+ }
625+ [ sym:: address] if set. value_str ( ) == Some ( sym:: on) => {
626+ result &= !SanitizerSet :: ADDRESS ;
627+ result &= !SanitizerSet :: KERNELADDRESS ;
628+ }
629+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: CFI ,
630+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: CFI ,
631+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: KCFI ,
632+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: KCFI ,
633+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: off) => {
634+ result |= SanitizerSet :: MEMORY
635+ }
636+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: on) => {
637+ result &= !SanitizerSet :: MEMORY
638+ }
639+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: off) => {
640+ result |= SanitizerSet :: MEMTAG
641+ }
642+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: on) => {
643+ result &= !SanitizerSet :: MEMTAG
644+ }
645+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: off) => {
646+ result |= SanitizerSet :: SHADOWCALLSTACK
647+ }
648+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: on) => {
649+ result &= !SanitizerSet :: SHADOWCALLSTACK
650+ }
651+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: off) => {
652+ result |= SanitizerSet :: THREAD
653+ }
654+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: on) => {
655+ result &= !SanitizerSet :: THREAD
656+ }
657+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: off) => {
658+ result |= SanitizerSet :: HWADDRESS
659+ }
660+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: on) => {
661+ result &= !SanitizerSet :: HWADDRESS
662+ }
663+ _ => {
664+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
665+ }
666+ }
667+ }
668+ }
669+ result
670+ }
671+
672+ fn disabled_sanitizers_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerSet {
673+ // Check for a sanitize annotation directly on this def.
674+ if let Some ( attr) = tcx. get_attr ( did, sym:: sanitize) {
675+ return parse_sanitize_attr ( tcx, attr) ;
676+ }
677+
678+ // Otherwise backtrack.
679+ match tcx. opt_local_parent ( did) {
680+ // Check the parent (recursively).
681+ Some ( parent) => tcx. disabled_sanitizers_for ( parent) ,
682+ // We reached the crate root without seeing an attribute, so
683+ // there is no sanitizers to exclude.
684+ None => SanitizerSet :: empty ( ) ,
685+ }
686+ }
687+
596688/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
597689/// applied to the method prototype.
598690fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
@@ -717,6 +809,11 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
717809}
718810
719811pub ( crate ) fn provide ( providers : & mut Providers ) {
720- * providers =
721- Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..* providers } ;
812+ * providers = Providers {
813+ codegen_fn_attrs,
814+ should_inherit_track_caller,
815+ inherited_align,
816+ disabled_sanitizers_for,
817+ ..* providers
818+ } ;
722819}
0 commit comments