@@ -162,6 +162,7 @@ fn parse_patchable_function_entry(
162
162
struct InterestingAttributeDiagnosticSpans {
163
163
link_ordinal : Option < Span > ,
164
164
no_sanitize : Option < Span > ,
165
+ sanitize : Option < Span > ,
165
166
inline : Option < Span > ,
166
167
no_mangle : Option < Span > ,
167
168
}
@@ -343,6 +344,7 @@ fn process_builtin_attrs(
343
344
codegen_fn_attrs. no_sanitize |=
344
345
parse_no_sanitize_attr ( tcx, attr) . unwrap_or_default ( ) ;
345
346
}
347
+ sym:: sanitize => interesting_spans. sanitize = Some ( attr. span ( ) ) ,
346
348
sym:: instruction_set => {
347
349
codegen_fn_attrs. instruction_set = parse_instruction_set_attr ( tcx, attr)
348
350
}
@@ -366,6 +368,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
366
368
codegen_fn_attrs. alignment =
367
369
Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
368
370
371
+ // Compute the disabled sanitizers.
372
+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
369
373
// On trait methods, inherit the `#[align]` of the trait's method prototype.
370
374
codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
371
375
@@ -471,6 +475,16 @@ fn check_result(
471
475
lint. span_note ( inline_span, "inlining requested here" ) ;
472
476
} )
473
477
}
478
+ if !codegen_fn_attrs. no_sanitize . is_empty ( )
479
+ && codegen_fn_attrs. inline . always ( )
480
+ && let ( Some ( sanitize_span) , Some ( inline_span) ) = ( interesting_spans. sanitize , interesting_spans. inline )
481
+ {
482
+ let hir_id = tcx. local_def_id_to_hir_id ( did) ;
483
+ tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, sanitize_span, |lint| {
484
+ lint. primary_message ( "setting `sanitize` off will have no effect after inlining" ) ;
485
+ lint. span_note ( inline_span, "inlining requested here" ) ;
486
+ } )
487
+ }
474
488
475
489
// error when specifying link_name together with link_ordinal
476
490
if let Some ( _) = codegen_fn_attrs. link_name
@@ -593,6 +607,84 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
593
607
}
594
608
}
595
609
610
+ /// For an attr that has the `sanitize` attribute, read the list of
611
+ /// disabled sanitizers.
612
+ fn parse_sanitize_attr ( tcx : TyCtxt < ' _ > , attr : & Attribute ) -> SanitizerSet {
613
+ let mut result = SanitizerSet :: empty ( ) ;
614
+ if let Some ( list) = attr. meta_item_list ( ) {
615
+ for item in list. iter ( ) {
616
+ let MetaItemInner :: MetaItem ( set) = item else {
617
+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
618
+ break ;
619
+ } ;
620
+ let segments = set. path . segments . iter ( ) . map ( |x| x. ident . name ) . collect :: < Vec < _ > > ( ) ;
621
+ match segments. as_slice ( ) {
622
+ [ sym:: address] if set. value_str ( ) == Some ( sym:: off) => {
623
+ result |= SanitizerSet :: ADDRESS | SanitizerSet :: KERNELADDRESS
624
+ }
625
+ [ sym:: address] if set. value_str ( ) == Some ( sym:: on) => {
626
+ result &= !SanitizerSet :: ADDRESS ;
627
+ result &= !SanitizerSet :: KERNELADDRESS ;
628
+ }
629
+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: CFI ,
630
+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: CFI ,
631
+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: KCFI ,
632
+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: KCFI ,
633
+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: off) => {
634
+ result |= SanitizerSet :: MEMORY
635
+ }
636
+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: on) => {
637
+ result &= !SanitizerSet :: MEMORY
638
+ }
639
+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: off) => {
640
+ result |= SanitizerSet :: MEMTAG
641
+ }
642
+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: on) => {
643
+ result &= !SanitizerSet :: MEMTAG
644
+ }
645
+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: off) => {
646
+ result |= SanitizerSet :: SHADOWCALLSTACK
647
+ }
648
+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: on) => {
649
+ result &= !SanitizerSet :: SHADOWCALLSTACK
650
+ }
651
+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: off) => {
652
+ result |= SanitizerSet :: THREAD
653
+ }
654
+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: on) => {
655
+ result &= !SanitizerSet :: THREAD
656
+ }
657
+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: off) => {
658
+ result |= SanitizerSet :: HWADDRESS
659
+ }
660
+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: on) => {
661
+ result &= !SanitizerSet :: HWADDRESS
662
+ }
663
+ _ => {
664
+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
665
+ }
666
+ }
667
+ }
668
+ }
669
+ result
670
+ }
671
+
672
+ fn disabled_sanitizers_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerSet {
673
+ // Check for a sanitize annotation directly on this def.
674
+ if let Some ( attr) = tcx. get_attr ( did, sym:: sanitize) {
675
+ return parse_sanitize_attr ( tcx, attr) ;
676
+ }
677
+
678
+ // Otherwise backtrack.
679
+ match tcx. opt_local_parent ( did) {
680
+ // Check the parent (recursively).
681
+ Some ( parent) => tcx. disabled_sanitizers_for ( parent) ,
682
+ // We reached the crate root without seeing an attribute, so
683
+ // there is no sanitizers to exclude.
684
+ None => SanitizerSet :: empty ( ) ,
685
+ }
686
+ }
687
+
596
688
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
597
689
/// applied to the method prototype.
598
690
fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
@@ -717,6 +809,11 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
717
809
}
718
810
719
811
pub ( crate ) fn provide ( providers : & mut Providers ) {
720
- * providers =
721
- Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..* providers } ;
812
+ * providers = Providers {
813
+ codegen_fn_attrs,
814
+ should_inherit_track_caller,
815
+ inherited_align,
816
+ disabled_sanitizers_for,
817
+ ..* providers
818
+ } ;
722
819
}
0 commit comments