@@ -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
}
@@ -335,6 +336,7 @@ fn process_builtin_attrs(
335
336
codegen_fn_attrs. no_sanitize |=
336
337
parse_no_sanitize_attr ( tcx, attr) . unwrap_or_default ( ) ;
337
338
}
339
+ sym:: sanitize => interesting_spans. sanitize = Some ( attr. span ( ) ) ,
338
340
sym:: instruction_set => {
339
341
codegen_fn_attrs. instruction_set = parse_instruction_set_attr ( tcx, attr)
340
342
}
@@ -358,6 +360,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
358
360
codegen_fn_attrs. alignment =
359
361
Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
360
362
363
+ // Compute the disabled sanitizers.
364
+ codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
361
365
// On trait methods, inherit the `#[align]` of the trait's method prototype.
362
366
codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
363
367
@@ -463,6 +467,17 @@ fn check_result(
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) ) =
473
+ ( interesting_spans. sanitize , interesting_spans. inline )
474
+ {
475
+ let hir_id = tcx. local_def_id_to_hir_id ( did) ;
476
+ tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, sanitize_span, |lint| {
477
+ lint. primary_message ( "setting `sanitize` off will have no effect after inlining" ) ;
478
+ lint. span_note ( inline_span, "inlining requested here" ) ;
479
+ } )
480
+ }
466
481
467
482
// error when specifying link_name together with link_ordinal
468
483
if let Some ( _) = codegen_fn_attrs. link_name
@@ -585,6 +600,84 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
585
600
}
586
601
}
587
602
603
+ /// For an attr that has the `sanitize` attribute, read the list of
604
+ /// disabled sanitizers.
605
+ fn parse_sanitize_attr ( tcx : TyCtxt < ' _ > , attr : & Attribute ) -> SanitizerSet {
606
+ let mut result = SanitizerSet :: empty ( ) ;
607
+ if let Some ( list) = attr. meta_item_list ( ) {
608
+ for item in list. iter ( ) {
609
+ let MetaItemInner :: MetaItem ( set) = item else {
610
+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
611
+ break ;
612
+ } ;
613
+ let segments = set. path . segments . iter ( ) . map ( |x| x. ident . name ) . collect :: < Vec < _ > > ( ) ;
614
+ match segments. as_slice ( ) {
615
+ [ sym:: address] if set. value_str ( ) == Some ( sym:: off) => {
616
+ result |= SanitizerSet :: ADDRESS | SanitizerSet :: KERNELADDRESS
617
+ }
618
+ [ sym:: address] if set. value_str ( ) == Some ( sym:: on) => {
619
+ result &= !SanitizerSet :: ADDRESS ;
620
+ result &= !SanitizerSet :: KERNELADDRESS ;
621
+ }
622
+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: CFI ,
623
+ [ sym:: cfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: CFI ,
624
+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: off) => result |= SanitizerSet :: KCFI ,
625
+ [ sym:: kcfi] if set. value_str ( ) == Some ( sym:: on) => result &= !SanitizerSet :: KCFI ,
626
+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: off) => {
627
+ result |= SanitizerSet :: MEMORY
628
+ }
629
+ [ sym:: memory] if set. value_str ( ) == Some ( sym:: on) => {
630
+ result &= !SanitizerSet :: MEMORY
631
+ }
632
+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: off) => {
633
+ result |= SanitizerSet :: MEMTAG
634
+ }
635
+ [ sym:: memtag] if set. value_str ( ) == Some ( sym:: on) => {
636
+ result &= !SanitizerSet :: MEMTAG
637
+ }
638
+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: off) => {
639
+ result |= SanitizerSet :: SHADOWCALLSTACK
640
+ }
641
+ [ sym:: shadow_call_stack] if set. value_str ( ) == Some ( sym:: on) => {
642
+ result &= !SanitizerSet :: SHADOWCALLSTACK
643
+ }
644
+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: off) => {
645
+ result |= SanitizerSet :: THREAD
646
+ }
647
+ [ sym:: thread] if set. value_str ( ) == Some ( sym:: on) => {
648
+ result &= !SanitizerSet :: THREAD
649
+ }
650
+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: off) => {
651
+ result |= SanitizerSet :: HWADDRESS
652
+ }
653
+ [ sym:: hwaddress] if set. value_str ( ) == Some ( sym:: on) => {
654
+ result &= !SanitizerSet :: HWADDRESS
655
+ }
656
+ _ => {
657
+ tcx. dcx ( ) . emit_err ( errors:: InvalidSanitize { span : attr. span ( ) } ) ;
658
+ }
659
+ }
660
+ }
661
+ }
662
+ result
663
+ }
664
+
665
+ fn disabled_sanitizers_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerSet {
666
+ // Check for a sanitize annotation directly on this def.
667
+ if let Some ( attr) = tcx. get_attr ( did, sym:: sanitize) {
668
+ return parse_sanitize_attr ( tcx, attr) ;
669
+ }
670
+
671
+ // Otherwise backtrack.
672
+ match tcx. opt_local_parent ( did) {
673
+ // Check the parent (recursively).
674
+ Some ( parent) => tcx. disabled_sanitizers_for ( parent) ,
675
+ // We reached the crate root without seeing an attribute, so
676
+ // there is no sanitizers to exclude.
677
+ None => SanitizerSet :: empty ( ) ,
678
+ }
679
+ }
680
+
588
681
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
589
682
/// applied to the method prototype.
590
683
fn should_inherit_track_caller ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
@@ -709,6 +802,11 @@ pub fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
709
802
}
710
803
711
804
pub ( crate ) fn provide ( providers : & mut Providers ) {
712
- * providers =
713
- Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..* providers } ;
805
+ * providers = Providers {
806
+ codegen_fn_attrs,
807
+ should_inherit_track_caller,
808
+ inherited_align,
809
+ disabled_sanitizers_for,
810
+ ..* providers
811
+ } ;
714
812
}
0 commit comments