@@ -9,7 +9,7 @@ use rustc_attr_data_structures::{
99use rustc_hir:: def:: DefKind ;
1010use rustc_hir:: def_id:: { DefId , LOCAL_CRATE , LocalDefId } ;
1111use rustc_hir:: weak_lang_items:: WEAK_LANG_ITEMS ;
12- use rustc_hir:: { self as hir, LangItem , lang_items} ;
12+ use rustc_hir:: { self as hir, Attribute , LangItem , lang_items} ;
1313use rustc_middle:: middle:: codegen_fn_attrs:: {
1414 CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry ,
1515} ;
@@ -87,6 +87,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
8787
8888 let mut link_ordinal_span = None ;
8989 let mut no_sanitize_span = None ;
90+ let mut sanitize_span = None ;
9091
9192 for attr in attrs. iter ( ) {
9293 // In some cases, attribute are only valid on functions, but it's the `check_attr`
@@ -287,6 +288,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
287288 }
288289 }
289290 }
291+ sym:: sanitize => sanitize_span = Some ( attr. span ( ) ) ,
290292 sym:: instruction_set => {
291293 codegen_fn_attrs. instruction_set =
292294 attr. meta_item_list ( ) . and_then ( |l| match & l[ ..] {
@@ -387,6 +389,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
387389 codegen_fn_attrs. alignment =
388390 Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
389391
392+ // Compute the disabled sanitizers.
393+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
390394 // On trait methods, inherit the `#[align]` of the trait's method prototype.
391395 codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
392396
@@ -461,6 +465,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
461465 lint. span_note ( inline_span, "inlining requested here" ) ;
462466 } )
463467 }
468+ if !codegen_fn_attrs. no_sanitize . is_empty ( )
469+ && codegen_fn_attrs. inline . always ( )
470+ && let ( Some ( sanitize_span) , Some ( inline_span) ) = ( sanitize_span, inline_span)
471+ {
472+ let hir_id = tcx. local_def_id_to_hir_id ( did) ;
473+ tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, sanitize_span, |lint| {
474+ lint. primary_message ( "setting `sanitize` off will have no effect after inlining" ) ;
475+ lint. span_note ( inline_span, "inlining requested here" ) ;
476+ } )
477+ }
464478
465479 // Weak lang items have the same semantics as "std internal" symbols in the
466480 // sense that they're preserved through all our LTO passes and only
@@ -553,6 +567,84 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
553567 }
554568}
555569
570+ /// For an attr that has the `sanitize` attribute, read the list of
571+ /// disabled sanitizers.
572+ fn parse_sanitize_attr ( tcx : TyCtxt < ' _ > , attr : & Attribute ) -> SanitizerSet {
573+ let mut result = SanitizerSet :: empty ( ) ;
574+ if let Some ( list) = attr. meta_item_list ( ) {
575+ for item in list. iter ( ) {
576+ let MetaItemInner :: MetaItem ( set) = item else {
577+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
578+ break ;
579+ } ;
580+ let segments = set. path . segments . iter ( ) . map ( |x| x. ident . name ) . collect :: < Vec < _ > > ( ) ;
581+ match segments. as_slice ( ) {
582+ [ sym:: address] if set. value_str ( ) == Some ( sym:: off) => {
583+ result |= SanitizerSet :: ADDRESS | SanitizerSet :: KERNELADDRESS
584+ }
585+ [ sym:: address] if set. value_str ( ) == Some ( sym:: on) => {
586+ result &= !SanitizerSet :: ADDRESS ;
587+ result &= !SanitizerSet :: KERNELADDRESS ;
588+ }
589+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: CFI ,
590+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: CFI ,
591+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: KCFI ,
592+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: KCFI ,
593+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: off) => {
594+ result |= SanitizerSet :: MEMORY
595+ }
596+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: on) => {
597+ result &= !SanitizerSet :: MEMORY
598+ }
599+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: off) => {
600+ result |= SanitizerSet :: MEMTAG
601+ }
602+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: on) => {
603+ result &= !SanitizerSet :: MEMTAG
604+ }
605+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: off) => {
606+ result |= SanitizerSet :: SHADOWCALLSTACK
607+ }
608+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: on) => {
609+ result &= !SanitizerSet :: SHADOWCALLSTACK
610+ }
611+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: off) => {
612+ result |= SanitizerSet :: THREAD
613+ }
614+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: on) => {
615+ result &= !SanitizerSet :: THREAD
616+ }
617+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: off) => {
618+ result |= SanitizerSet :: HWADDRESS
619+ }
620+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: on) => {
621+ result &= !SanitizerSet :: HWADDRESS
622+ }
623+ _ => {
624+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
625+ }
626+ }
627+ }
628+ }
629+ result
630+ }
631+
632+ fn disabled_sanitizers_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerSet {
633+ // Check for a sanitize annotation directly on this def.
634+ if let Some ( attr) = tcx. get_attr ( did, sym:: sanitize) {
635+ return parse_sanitize_attr ( tcx, attr) ;
636+ }
637+
638+ // Otherwise backtrack.
639+ match tcx. opt_local_parent ( did) {
640+ // Check the parent (recursively).
641+ Some ( parent) => tcx. disabled_sanitizers_for ( parent) ,
642+ // We reached the crate root without seeing an attribute, so
643+ // there is no sanitizers to exclude.
644+ None => SanitizerSet :: empty ( ) ,
645+ }
646+ }
647+
556648/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
557649/// applied to the method prototype.
558650fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
@@ -692,6 +784,11 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
692784}
693785
694786pub ( crate ) fn provide ( providers : & mut Providers ) {
695- * providers =
696- Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..* providers } ;
787+ * providers = Providers {
788+ codegen_fn_attrs,
789+ should_inherit_track_caller,
790+ inherited_align,
791+ disabled_sanitizers_for,
792+ ..* providers
793+ } ;
697794}
0 commit comments