@@ -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`
@@ -289,6 +290,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
289290 }
290291 }
291292 }
293+ sym:: sanitize => sanitize_span = Some ( attr. span ( ) ) ,
292294 sym:: instruction_set => {
293295 codegen_fn_attrs. instruction_set =
294296 attr. meta_item_list ( ) . and_then ( |l| match & l[ ..] {
@@ -389,6 +391,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
389391 codegen_fn_attrs. alignment =
390392 Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
391393
394+ // Compute the disabled sanitizers.
395+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
392396 // On trait methods, inherit the `#[align]` of the trait's method prototype.
393397 codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
394398
@@ -463,6 +467,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
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) ) = ( sanitize_span, inline_span)
473+ {
474+ let hir_id = tcx. local_def_id_to_hir_id ( did) ;
475+ tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, sanitize_span, |lint| {
476+ lint. primary_message ( "setting `sanitize` off will have no effect after inlining" ) ;
477+ lint. span_note ( inline_span, "inlining requested here" ) ;
478+ } )
479+ }
466480
467481 // Weak lang items have the same semantics as "std internal" symbols in the
468482 // sense that they're preserved through all our LTO passes and only
@@ -555,6 +569,84 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
555569 }
556570}
557571
572+ /// For an attr that has the `sanitize` attribute, read the list of
573+ /// disabled sanitizers.
574+ fn parse_sanitize_attr ( tcx : TyCtxt < ' _ > , attr : & Attribute ) -> SanitizerSet {
575+ let mut result = SanitizerSet :: empty ( ) ;
576+ if let Some ( list) = attr. meta_item_list ( ) {
577+ for item in list. iter ( ) {
578+ let MetaItemInner :: MetaItem ( set) = item else {
579+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
580+ break ;
581+ } ;
582+ let segments = set. path . segments . iter ( ) . map ( |x| x. ident . name ) . collect :: < Vec < _ > > ( ) ;
583+ match segments. as_slice ( ) {
584+ [ sym:: address] if set. value_str ( ) == Some ( sym:: off) => {
585+ result |= SanitizerSet :: ADDRESS | SanitizerSet :: KERNELADDRESS
586+ }
587+ [ sym:: address] if set. value_str ( ) == Some ( sym:: on) => {
588+ result &= !SanitizerSet :: ADDRESS ;
589+ result &= !SanitizerSet :: KERNELADDRESS ;
590+ }
591+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: CFI ,
592+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: CFI ,
593+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: KCFI ,
594+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: KCFI ,
595+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: off) => {
596+ result |= SanitizerSet :: MEMORY
597+ }
598+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: on) => {
599+ result &= !SanitizerSet :: MEMORY
600+ }
601+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: off) => {
602+ result |= SanitizerSet :: MEMTAG
603+ }
604+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: on) => {
605+ result &= !SanitizerSet :: MEMTAG
606+ }
607+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: off) => {
608+ result |= SanitizerSet :: SHADOWCALLSTACK
609+ }
610+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: on) => {
611+ result &= !SanitizerSet :: SHADOWCALLSTACK
612+ }
613+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: off) => {
614+ result |= SanitizerSet :: THREAD
615+ }
616+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: on) => {
617+ result &= !SanitizerSet :: THREAD
618+ }
619+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: off) => {
620+ result |= SanitizerSet :: HWADDRESS
621+ }
622+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: on) => {
623+ result &= !SanitizerSet :: HWADDRESS
624+ }
625+ _ => {
626+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
627+ }
628+ }
629+ }
630+ }
631+ result
632+ }
633+
634+ fn disabled_sanitizers_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerSet {
635+ // Check for a sanitize annotation directly on this def.
636+ if let Some ( attr) = tcx. get_attr ( did, sym:: sanitize) {
637+ return parse_sanitize_attr ( tcx, attr) ;
638+ }
639+
640+ // Otherwise backtrack.
641+ match tcx. opt_local_parent ( did) {
642+ // Check the parent (recursively).
643+ Some ( parent) => tcx. disabled_sanitizers_for ( parent) ,
644+ // We reached the crate root without seeing an attribute, so
645+ // there is no sanitizers to exclude.
646+ None => SanitizerSet :: empty ( ) ,
647+ }
648+ }
649+
558650/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
559651/// applied to the method prototype.
560652fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
@@ -733,6 +825,11 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
733825}
734826
735827pub ( crate ) fn provide ( providers : & mut Providers ) {
736- * providers =
737- Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..* providers } ;
828+ * providers = Providers {
829+ codegen_fn_attrs,
830+ should_inherit_track_caller,
831+ inherited_align,
832+ disabled_sanitizers_for,
833+ ..* providers
834+ } ;
738835}
0 commit comments