@@ -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`
@@ -289,6 +290,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
289
290
}
290
291
}
291
292
}
293
+ sym:: sanitize => sanitize_span = Some ( attr. span ( ) ) ,
292
294
sym:: instruction_set => {
293
295
codegen_fn_attrs. instruction_set =
294
296
attr. meta_item_list ( ) . and_then ( |l| match & l[ ..] {
@@ -389,6 +391,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
389
391
codegen_fn_attrs. alignment =
390
392
Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
391
393
394
+ // Compute the disabled sanitizers.
395
+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
392
396
// On trait methods, inherit the `#[align]` of the trait's method prototype.
393
397
codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
394
398
@@ -463,6 +467,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
463
467
lint. span_note ( inline_span, "inlining requested here" ) ;
464
468
} )
465
469
}
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
+ }
466
480
467
481
// Weak lang items have the same semantics as "std internal" symbols in the
468
482
// 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> {
555
569
}
556
570
}
557
571
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
+
558
650
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
559
651
/// applied to the method prototype.
560
652
fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
@@ -733,6 +825,11 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
733
825
}
734
826
735
827
pub ( 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
+ } ;
738
835
}
0 commit comments