@@ -9,7 +9,7 @@ use rustc_data_structures::fx::FxHashMap;
9
9
use rustc_hir:: def:: DefKind ;
10
10
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE , LocalDefId } ;
11
11
use 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} ;
13
13
use rustc_middle:: middle:: codegen_fn_attrs:: {
14
14
CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry ,
15
15
} ;
@@ -86,6 +86,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
86
86
let mut inline_span = None ;
87
87
let mut link_ordinal_span = None ;
88
88
let mut no_sanitize_span = None ;
89
+ let mut sanitize_span = None ;
89
90
let mut mixed_export_name_no_mangle_lint_state = MixedExportNameAndNoMangleState :: default ( ) ;
90
91
let mut no_mangle_span = None ;
91
92
@@ -353,6 +354,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
353
354
}
354
355
}
355
356
}
357
+ sym:: sanitize => sanitize_span = Some ( attr. span ( ) ) ,
356
358
sym:: instruction_set => {
357
359
codegen_fn_attrs. instruction_set =
358
360
attr. meta_item_list ( ) . and_then ( |l| match & l[ ..] {
@@ -447,6 +449,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
447
449
}
448
450
}
449
451
452
+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
450
453
mixed_export_name_no_mangle_lint_state. lint_if_mixed ( tcx) ;
451
454
452
455
codegen_fn_attrs. inline = attrs. iter ( ) . fold ( InlineAttr :: None , |ia, attr| {
@@ -580,6 +583,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
580
583
lint. span_note ( inline_span, "inlining requested here" ) ;
581
584
} )
582
585
}
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
+ }
583
596
584
597
// Weak lang items have the same semantics as "std internal" symbols in the
585
598
// 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 {
660
673
codegen_fn_attrs
661
674
}
662
675
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
+
663
754
/// Given a map from target_features to whether they are enabled or disabled, ensure only valid
664
755
/// combinations are allowed.
665
756
pub fn check_tied_features (
@@ -900,5 +991,10 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
900
991
}
901
992
902
993
pub ( 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
+ } ;
904
1000
}
0 commit comments