@@ -195,6 +195,7 @@ fn parse_patchable_function_entry(
195
195
struct InterestingAttributeDiagnosticSpans {
196
196
link_ordinal : Option < Span > ,
197
197
no_sanitize : Option < Span > ,
198
+ sanitize : Option < Span > ,
198
199
inline : Option < Span > ,
199
200
no_mangle : Option < Span > ,
200
201
}
@@ -376,6 +377,7 @@ fn process_builtin_attrs(
376
377
codegen_fn_attrs. no_sanitize |=
377
378
parse_no_sanitize_attr ( tcx, attr) . unwrap_or_default ( ) ;
378
379
}
380
+ sym:: sanitize => interesting_spans. sanitize = Some ( attr. span ( ) ) ,
379
381
sym:: instruction_set => {
380
382
codegen_fn_attrs. instruction_set = parse_instruction_set_attr ( tcx, attr)
381
383
}
@@ -399,6 +401,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
399
401
codegen_fn_attrs. alignment =
400
402
Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
401
403
404
+ // Compute the disabled sanitizers.
405
+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
402
406
// On trait methods, inherit the `#[align]` of the trait's method prototype.
403
407
codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
404
408
@@ -483,6 +487,16 @@ fn check_result(
483
487
lint. span_note ( inline_span, "inlining requested here" ) ;
484
488
} )
485
489
}
490
+ if !codegen_fn_attrs. no_sanitize . is_empty ( )
491
+ && codegen_fn_attrs. inline . always ( )
492
+ && let ( Some ( sanitize_span) , Some ( inline_span) ) = ( interesting_spans. sanitize , interesting_spans. inline )
493
+ {
494
+ let hir_id = tcx. local_def_id_to_hir_id ( did) ;
495
+ tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, sanitize_span, |lint| {
496
+ lint. primary_message ( "setting `sanitize` off will have no effect after inlining" ) ;
497
+ lint. span_note ( inline_span, "inlining requested here" ) ;
498
+ } )
499
+ }
486
500
487
501
// error when specifying link_name together with link_ordinal
488
502
if let Some ( _) = codegen_fn_attrs. link_name
@@ -605,6 +619,84 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
605
619
}
606
620
}
607
621
622
+ /// For an attr that has the `sanitize` attribute, read the list of
623
+ /// disabled sanitizers.
624
+ fn parse_sanitize_attr ( tcx : TyCtxt < ' _ > , attr : & Attribute ) -> SanitizerSet {
625
+ let mut result = SanitizerSet :: empty ( ) ;
626
+ if let Some ( list) = attr. meta_item_list ( ) {
627
+ for item in list. iter ( ) {
628
+ let MetaItemInner :: MetaItem ( set) = item else {
629
+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
630
+ break ;
631
+ } ;
632
+ let segments = set. path . segments . iter ( ) . map ( |x| x. ident . name ) . collect :: < Vec < _ > > ( ) ;
633
+ match segments. as_slice ( ) {
634
+ [ sym:: address] if set. value_str ( ) == Some ( sym:: off) => {
635
+ result |= SanitizerSet :: ADDRESS | SanitizerSet :: KERNELADDRESS
636
+ }
637
+ [ sym:: address] if set. value_str ( ) == Some ( sym:: on) => {
638
+ result &= !SanitizerSet :: ADDRESS ;
639
+ result &= !SanitizerSet :: KERNELADDRESS ;
640
+ }
641
+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: CFI ,
642
+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: CFI ,
643
+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: KCFI ,
644
+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: KCFI ,
645
+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: off) => {
646
+ result |= SanitizerSet :: MEMORY
647
+ }
648
+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: on) => {
649
+ result &= !SanitizerSet :: MEMORY
650
+ }
651
+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: off) => {
652
+ result |= SanitizerSet :: MEMTAG
653
+ }
654
+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: on) => {
655
+ result &= !SanitizerSet :: MEMTAG
656
+ }
657
+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: off) => {
658
+ result |= SanitizerSet :: SHADOWCALLSTACK
659
+ }
660
+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: on) => {
661
+ result &= !SanitizerSet :: SHADOWCALLSTACK
662
+ }
663
+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: off) => {
664
+ result |= SanitizerSet :: THREAD
665
+ }
666
+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: on) => {
667
+ result &= !SanitizerSet :: THREAD
668
+ }
669
+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: off) => {
670
+ result |= SanitizerSet :: HWADDRESS
671
+ }
672
+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: on) => {
673
+ result &= !SanitizerSet :: HWADDRESS
674
+ }
675
+ _ => {
676
+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
677
+ }
678
+ }
679
+ }
680
+ }
681
+ result
682
+ }
683
+
684
+ fn disabled_sanitizers_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerSet {
685
+ // Check for a sanitize annotation directly on this def.
686
+ if let Some ( attr) = tcx. get_attr ( did, sym:: sanitize) {
687
+ return parse_sanitize_attr ( tcx, attr) ;
688
+ }
689
+
690
+ // Otherwise backtrack.
691
+ match tcx. opt_local_parent ( did) {
692
+ // Check the parent (recursively).
693
+ Some ( parent) => tcx. disabled_sanitizers_for ( parent) ,
694
+ // We reached the crate root without seeing an attribute, so
695
+ // there is no sanitizers to exclude.
696
+ None => SanitizerSet :: empty ( ) ,
697
+ }
698
+ }
699
+
608
700
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
609
701
/// applied to the method prototype.
610
702
fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
@@ -729,6 +821,11 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
729
821
}
730
822
731
823
pub ( crate ) fn provide ( providers : & mut Providers ) {
732
- * providers =
733
- Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..* providers } ;
824
+ * providers = Providers {
825
+ codegen_fn_attrs,
826
+ should_inherit_track_caller,
827
+ inherited_align,
828
+ disabled_sanitizers_for,
829
+ ..* providers
830
+ } ;
734
831
}
0 commit comments