@@ -9,7 +9,7 @@ use rustc_attr_data_structures::{
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, LangItem , lang_items} ;
12
+ use rustc_hir:: { self as hir, Attribute , LangItem , lang_items} ;
13
13
use rustc_middle:: middle:: codegen_fn_attrs:: {
14
14
CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry ,
15
15
} ;
@@ -87,6 +87,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
87
87
88
88
let mut link_ordinal_span = None ;
89
89
let mut no_sanitize_span = None ;
90
+ let mut sanitize_span = None ;
90
91
91
92
for attr in attrs. iter ( ) {
92
93
// 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 {
287
288
}
288
289
}
289
290
}
291
+ sym:: sanitize => sanitize_span = Some ( attr. span ( ) ) ,
290
292
sym:: instruction_set => {
291
293
codegen_fn_attrs. instruction_set =
292
294
attr. meta_item_list ( ) . and_then ( |l| match & l[ ..] {
@@ -387,6 +389,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
387
389
codegen_fn_attrs. alignment =
388
390
Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
389
391
392
+ // Compute the disabled sanitizers.
393
+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
390
394
// On trait methods, inherit the `#[align]` of the trait's method prototype.
391
395
codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
392
396
@@ -461,6 +465,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
461
465
lint. span_note ( inline_span, "inlining requested here" ) ;
462
466
} )
463
467
}
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
+ }
464
478
465
479
// Weak lang items have the same semantics as "std internal" symbols in the
466
480
// 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> {
553
567
}
554
568
}
555
569
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
+
556
648
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
557
649
/// applied to the method prototype.
558
650
fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
@@ -692,6 +784,11 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
692
784
}
693
785
694
786
pub ( 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
+ } ;
697
794
}
0 commit comments