@@ -195,6 +195,7 @@ fn parse_patchable_function_entry(
195195struct InterestingAttributeDiagnosticSpans {
196196 link_ordinal : Option < Span > ,
197197 no_sanitize : Option < Span > ,
198+ sanitize : Option < Span > ,
198199 inline : Option < Span > ,
199200 no_mangle : Option < Span > ,
200201}
@@ -376,6 +377,7 @@ fn process_builtin_attrs(
376377 codegen_fn_attrs. no_sanitize |=
377378 parse_no_sanitize_attr ( tcx, attr) . unwrap_or_default ( ) ;
378379 }
380+ sym:: sanitize => interesting_spans. sanitize = Some ( attr. span ( ) ) ,
379381 sym:: instruction_set => {
380382 codegen_fn_attrs. instruction_set = parse_instruction_set_attr ( tcx, attr)
381383 }
@@ -399,6 +401,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
399401 codegen_fn_attrs. alignment =
400402 Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
401403
404+ // Compute the disabled sanitizers.
405+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
402406 // On trait methods, inherit the `#[align]` of the trait's method prototype.
403407 codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
404408
@@ -483,6 +487,16 @@ fn check_result(
483487 lint. span_note ( inline_span, "inlining requested here" ) ;
484488 } )
485489 }
490+ if !codegen_fn_attrs. no_sanitize . is_empty ( )
491+ && codegen_fn_attrs. inline . always ( )
492+ && let ( Some ( sanitize_span) , Some ( inline_span) ) = ( interesting_spans. sanitize , interesting_spans. inline )
493+ {
494+ let hir_id = tcx. local_def_id_to_hir_id ( did) ;
495+ tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, sanitize_span, |lint| {
496+ lint. primary_message ( "setting `sanitize` off will have no effect after inlining" ) ;
497+ lint. span_note ( inline_span, "inlining requested here" ) ;
498+ } )
499+ }
486500
487501 // error when specifying link_name together with link_ordinal
488502 if let Some ( _) = codegen_fn_attrs. link_name
@@ -605,6 +619,84 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
605619 }
606620}
607621
622+ /// For an attr that has the `sanitize` attribute, read the list of
623+ /// disabled sanitizers.
624+ fn parse_sanitize_attr ( tcx : TyCtxt < ' _ > , attr : & Attribute ) -> SanitizerSet {
625+ let mut result = SanitizerSet :: empty ( ) ;
626+ if let Some ( list) = attr. meta_item_list ( ) {
627+ for item in list. iter ( ) {
628+ let MetaItemInner :: MetaItem ( set) = item else {
629+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
630+ break ;
631+ } ;
632+ let segments = set. path . segments . iter ( ) . map ( |x| x. ident . name ) . collect :: < Vec < _ > > ( ) ;
633+ match segments. as_slice ( ) {
634+ [ sym:: address] if set. value_str ( ) == Some ( sym:: off) => {
635+ result |= SanitizerSet :: ADDRESS | SanitizerSet :: KERNELADDRESS
636+ }
637+ [ sym:: address] if set. value_str ( ) == Some ( sym:: on) => {
638+ result &= !SanitizerSet :: ADDRESS ;
639+ result &= !SanitizerSet :: KERNELADDRESS ;
640+ }
641+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: CFI ,
642+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: CFI ,
643+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: KCFI ,
644+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: KCFI ,
645+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: off) => {
646+ result |= SanitizerSet :: MEMORY
647+ }
648+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: on) => {
649+ result &= !SanitizerSet :: MEMORY
650+ }
651+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: off) => {
652+ result |= SanitizerSet :: MEMTAG
653+ }
654+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: on) => {
655+ result &= !SanitizerSet :: MEMTAG
656+ }
657+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: off) => {
658+ result |= SanitizerSet :: SHADOWCALLSTACK
659+ }
660+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: on) => {
661+ result &= !SanitizerSet :: SHADOWCALLSTACK
662+ }
663+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: off) => {
664+ result |= SanitizerSet :: THREAD
665+ }
666+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: on) => {
667+ result &= !SanitizerSet :: THREAD
668+ }
669+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: off) => {
670+ result |= SanitizerSet :: HWADDRESS
671+ }
672+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: on) => {
673+ result &= !SanitizerSet :: HWADDRESS
674+ }
675+ _ => {
676+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
677+ }
678+ }
679+ }
680+ }
681+ result
682+ }
683+
684+ fn disabled_sanitizers_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerSet {
685+ // Check for a sanitize annotation directly on this def.
686+ if let Some ( attr) = tcx. get_attr ( did, sym:: sanitize) {
687+ return parse_sanitize_attr ( tcx, attr) ;
688+ }
689+
690+ // Otherwise backtrack.
691+ match tcx. opt_local_parent ( did) {
692+ // Check the parent (recursively).
693+ Some ( parent) => tcx. disabled_sanitizers_for ( parent) ,
694+ // We reached the crate root without seeing an attribute, so
695+ // there is no sanitizers to exclude.
696+ None => SanitizerSet :: empty ( ) ,
697+ }
698+ }
699+
608700/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
609701/// applied to the method prototype.
610702fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
@@ -729,6 +821,11 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
729821}
730822
731823pub ( crate ) fn provide ( providers : & mut Providers ) {
732- * providers =
733- Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..* providers } ;
824+ * providers = Providers {
825+ codegen_fn_attrs,
826+ should_inherit_track_caller,
827+ inherited_align,
828+ disabled_sanitizers_for,
829+ ..* providers
830+ } ;
734831}
0 commit comments