@@ -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}
@@ -335,6 +336,7 @@ fn process_builtin_attrs(
335336 codegen_fn_attrs. no_sanitize |=
336337 parse_no_sanitize_attr ( tcx, attr) . unwrap_or_default ( ) ;
337338 }
339+ sym:: sanitize => interesting_spans. sanitize = Some ( attr. span ( ) ) ,
338340 sym:: instruction_set => {
339341 codegen_fn_attrs. instruction_set = parse_instruction_set_attr ( tcx, attr)
340342 }
@@ -358,6 +360,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
358360 codegen_fn_attrs. alignment =
359361 Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
360362
363+ // Compute the disabled sanitizers.
364+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
361365 // On trait methods, inherit the `#[align]` of the trait's method prototype.
362366 codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
363367
@@ -463,6 +467,17 @@ fn check_result(
463467 lint. span_note ( inline_span, "inlining requested here" ) ;
464468 } )
465469 }
470+ if !codegen_fn_attrs. no_sanitize . is_empty ( )
471+ && codegen_fn_attrs. inline . always ( )
472+ && let ( Some ( sanitize_span) , Some ( inline_span) ) =
473+ ( interesting_spans. sanitize , interesting_spans. inline )
474+ {
475+ let hir_id = tcx. local_def_id_to_hir_id ( did) ;
476+ tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, sanitize_span, |lint| {
477+ lint. primary_message ( "setting `sanitize` off will have no effect after inlining" ) ;
478+ lint. span_note ( inline_span, "inlining requested here" ) ;
479+ } )
480+ }
466481
467482 // error when specifying link_name together with link_ordinal
468483 if let Some ( _) = codegen_fn_attrs. link_name
@@ -585,6 +600,84 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
585600 }
586601}
587602
603+ /// For an attr that has the `sanitize` attribute, read the list of
604+ /// disabled sanitizers.
605+ fn parse_sanitize_attr ( tcx : TyCtxt < ' _ > , attr : & Attribute ) -> SanitizerSet {
606+ let mut result = SanitizerSet :: empty ( ) ;
607+ if let Some ( list) = attr. meta_item_list ( ) {
608+ for item in list. iter ( ) {
609+ let MetaItemInner :: MetaItem ( set) = item else {
610+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
611+ break ;
612+ } ;
613+ let segments = set. path . segments . iter ( ) . map ( |x| x. ident . name ) . collect :: < Vec < _ > > ( ) ;
614+ match segments. as_slice ( ) {
615+ [ sym:: address] if set. value_str ( ) == Some ( sym:: off) => {
616+ result |= SanitizerSet :: ADDRESS | SanitizerSet :: KERNELADDRESS
617+ }
618+ [ sym:: address] if set. value_str ( ) == Some ( sym:: on) => {
619+ result &= !SanitizerSet :: ADDRESS ;
620+ result &= !SanitizerSet :: KERNELADDRESS ;
621+ }
622+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: CFI ,
623+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: CFI ,
624+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: KCFI ,
625+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: KCFI ,
626+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: off) => {
627+ result |= SanitizerSet :: MEMORY
628+ }
629+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: on) => {
630+ result &= !SanitizerSet :: MEMORY
631+ }
632+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: off) => {
633+ result |= SanitizerSet :: MEMTAG
634+ }
635+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: on) => {
636+ result &= !SanitizerSet :: MEMTAG
637+ }
638+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: off) => {
639+ result |= SanitizerSet :: SHADOWCALLSTACK
640+ }
641+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: on) => {
642+ result &= !SanitizerSet :: SHADOWCALLSTACK
643+ }
644+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: off) => {
645+ result |= SanitizerSet :: THREAD
646+ }
647+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: on) => {
648+ result &= !SanitizerSet :: THREAD
649+ }
650+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: off) => {
651+ result |= SanitizerSet :: HWADDRESS
652+ }
653+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: on) => {
654+ result &= !SanitizerSet :: HWADDRESS
655+ }
656+ _ => {
657+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
658+ }
659+ }
660+ }
661+ }
662+ result
663+ }
664+
665+ fn disabled_sanitizers_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerSet {
666+ // Check for a sanitize annotation directly on this def.
667+ if let Some ( attr) = tcx. get_attr ( did, sym:: sanitize) {
668+ return parse_sanitize_attr ( tcx, attr) ;
669+ }
670+
671+ // Otherwise backtrack.
672+ match tcx. opt_local_parent ( did) {
673+ // Check the parent (recursively).
674+ Some ( parent) => tcx. disabled_sanitizers_for ( parent) ,
675+ // We reached the crate root without seeing an attribute, so
676+ // there is no sanitizers to exclude.
677+ None => SanitizerSet :: empty ( ) ,
678+ }
679+ }
680+
588681/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
589682/// applied to the method prototype.
590683fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
@@ -709,6 +802,11 @@ pub fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
709802}
710803
711804pub ( crate ) fn provide ( providers : & mut Providers ) {
712- * providers =
713- Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..* providers } ;
805+ * providers = Providers {
806+ codegen_fn_attrs,
807+ should_inherit_track_caller,
808+ inherited_align,
809+ disabled_sanitizers_for,
810+ ..* providers
811+ } ;
714812}
0 commit comments