@@ -9,7 +9,7 @@ use rustc_data_structures::fx::FxHashMap;
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, HirId , LangItem , lang_items} ;
12+ use rustc_hir:: { self as hir, Attribute , HirId , LangItem , lang_items} ;
1313use rustc_middle:: middle:: codegen_fn_attrs:: {
1414 CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry ,
1515} ;
@@ -86,6 +86,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
8686 let mut inline_span = None ;
8787 let mut link_ordinal_span = None ;
8888 let mut no_sanitize_span = None ;
89+ let mut sanitize_span = None ;
8990 let mut mixed_export_name_no_mangle_lint_state = MixedExportNameAndNoMangleState :: default ( ) ;
9091 let mut no_mangle_span = None ;
9192
@@ -353,6 +354,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
353354 }
354355 }
355356 }
357+ sym:: sanitize => sanitize_span = Some ( attr. span ( ) ) ,
356358 sym:: instruction_set => {
357359 codegen_fn_attrs. instruction_set =
358360 attr. meta_item_list ( ) . and_then ( |l| match & l[ ..] {
@@ -447,6 +449,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
447449 }
448450 }
449451
452+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
450453 mixed_export_name_no_mangle_lint_state. lint_if_mixed ( tcx) ;
451454
452455 codegen_fn_attrs. inline = attrs. iter ( ) . fold ( InlineAttr :: None , |ia, attr| {
@@ -580,6 +583,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
580583 lint. span_note ( inline_span, "inlining requested here" ) ;
581584 } )
582585 }
586+ if !codegen_fn_attrs. no_sanitize . is_empty ( )
587+ && codegen_fn_attrs. inline . always ( )
588+ && let ( Some ( sanitize_span) , Some ( inline_span) ) = ( sanitize_span, inline_span)
589+ {
590+ let hir_id = tcx. local_def_id_to_hir_id ( did) ;
591+ tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, sanitize_span, |lint| {
592+ lint. primary_message ( "setting `sanitize` off will have no effect after inlining" ) ;
593+ lint. span_note ( inline_span, "inlining requested here" ) ;
594+ } )
595+ }
583596
584597 // Weak lang items have the same semantics as "std internal" symbols in the
585598 // sense that they're preserved through all our LTO passes and only
@@ -660,6 +673,84 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
660673 codegen_fn_attrs
661674}
662675
676+ /// For an attr that has the `sanitize` attribute, read the list of
677+ /// disabled sanitizers.
678+ fn parse_sanitize_attr ( tcx : TyCtxt < ' _ > , attr : & Attribute ) -> SanitizerSet {
679+ let mut result = SanitizerSet :: empty ( ) ;
680+ if let Some ( list) = attr. meta_item_list ( ) {
681+ for item in list. iter ( ) {
682+ let MetaItemInner :: MetaItem ( set) = item else {
683+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
684+ break ;
685+ } ;
686+ let segments = set. path . segments . iter ( ) . map ( |x| x. ident . name ) . collect :: < Vec < _ > > ( ) ;
687+ match segments. as_slice ( ) {
688+ [ sym:: address] if set. value_str ( ) == Some ( sym:: off) => {
689+ result |= SanitizerSet :: ADDRESS | SanitizerSet :: KERNELADDRESS
690+ }
691+ [ sym:: address] if set. value_str ( ) == Some ( sym:: on) => {
692+ result &= !SanitizerSet :: ADDRESS ;
693+ result &= !SanitizerSet :: KERNELADDRESS ;
694+ }
695+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: CFI ,
696+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: CFI ,
697+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: KCFI ,
698+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: KCFI ,
699+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: off) => {
700+ result |= SanitizerSet :: MEMORY
701+ }
702+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: on) => {
703+ result &= !SanitizerSet :: MEMORY
704+ }
705+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: off) => {
706+ result |= SanitizerSet :: MEMTAG
707+ }
708+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: on) => {
709+ result &= !SanitizerSet :: MEMTAG
710+ }
711+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: off) => {
712+ result |= SanitizerSet :: SHADOWCALLSTACK
713+ }
714+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: on) => {
715+ result &= !SanitizerSet :: SHADOWCALLSTACK
716+ }
717+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: off) => {
718+ result |= SanitizerSet :: THREAD
719+ }
720+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: on) => {
721+ result &= !SanitizerSet :: THREAD
722+ }
723+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: off) => {
724+ result |= SanitizerSet :: HWADDRESS
725+ }
726+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: on) => {
727+ result &= !SanitizerSet :: HWADDRESS
728+ }
729+ _ => {
730+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
731+ }
732+ }
733+ }
734+ }
735+ result
736+ }
737+
738+ fn disabled_sanitizers_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerSet {
739+ // Check for a sanitize annotation directly on this def.
740+ if let Some ( attr) = tcx. get_attr ( did, sym:: sanitize) {
741+ return parse_sanitize_attr ( tcx, attr) ;
742+ }
743+
744+ // Otherwise backtrack.
745+ match tcx. opt_local_parent ( did) {
746+ // Check the parent (recursively).
747+ Some ( parent) => tcx. disabled_sanitizers_for ( parent) ,
748+ // We reached the crate root without seeing an attribute, so
749+ // there is no sanitizers to exclude.
750+ None => SanitizerSet :: empty ( ) ,
751+ }
752+ }
753+
663754/// Given a map from target_features to whether they are enabled or disabled, ensure only valid
664755/// combinations are allowed.
665756pub fn check_tied_features (
@@ -900,5 +991,10 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
900991}
901992
902993pub ( crate ) fn provide ( providers : & mut Providers ) {
903- * providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..* providers } ;
994+ * providers = Providers {
995+ codegen_fn_attrs,
996+ should_inherit_track_caller,
997+ disabled_sanitizers_for,
998+ ..* providers
999+ } ;
9041000}
0 commit comments