@@ -3,20 +3,19 @@ use std::str::FromStr;
33use rustc_abi:: { Align , ExternAbi } ;
44use rustc_ast:: expand:: autodiff_attrs:: { AutoDiffAttrs , DiffActivity , DiffMode } ;
55use rustc_ast:: { LitKind , MetaItem , MetaItemInner , attr} ;
6- use rustc_hir:: attrs:: { AttributeKind , InlineAttr , InstructionSetAttr , UsedBy } ;
6+ use rustc_hir:: attrs:: { AttributeKind , InlineAttr , InstructionSetAttr , RtsanSetting , UsedBy } ;
77use rustc_hir:: def:: DefKind ;
88use rustc_hir:: def_id:: { DefId , LOCAL_CRATE , LocalDefId } ;
99use rustc_hir:: { self as hir, Attribute , LangItem , find_attr, lang_items} ;
1010use rustc_middle:: middle:: codegen_fn_attrs:: {
11- CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry ,
11+ CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry , SanitizerFnAttrs ,
1212} ;
1313use rustc_middle:: query:: Providers ;
1414use rustc_middle:: span_bug;
1515use rustc_middle:: ty:: { self as ty, TyCtxt } ;
1616use rustc_session:: lint;
1717use rustc_session:: parse:: feature_err;
1818use rustc_span:: { Ident , Span , sym} ;
19- use rustc_target:: spec:: SanitizerSet ;
2019
2120use crate :: errors;
2221use crate :: target_features:: {
@@ -350,8 +349,10 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
350349 codegen_fn_attrs. alignment =
351350 Ord :: max ( codegen_fn_attrs. alignment , tcx. sess . opts . unstable_opts . min_function_alignment ) ;
352351
353- // Compute the disabled sanitizers.
354- codegen_fn_attrs. no_sanitize |= tcx. disabled_sanitizers_for ( did) ;
352+ // Passed in sanitizer settings are always the default.
353+ assert ! ( codegen_fn_attrs. sanitizers == SanitizerFnAttrs :: default ( ) ) ;
354+ // Replace with #[sanitize] value
355+ codegen_fn_attrs. sanitizers = tcx. sanitizer_settings_for ( did) ;
355356 // On trait methods, inherit the `#[align]` of the trait's method prototype.
356357 codegen_fn_attrs. alignment = Ord :: max ( codegen_fn_attrs. alignment , tcx. inherited_align ( did) ) ;
357358
@@ -455,18 +456,40 @@ fn check_result(
455456 }
456457
457458 // warn that inline has no effect when no_sanitize is present
458- if ! codegen_fn_attrs. no_sanitize . is_empty ( )
459+ if codegen_fn_attrs. sanitizers != SanitizerFnAttrs :: default ( )
459460 && codegen_fn_attrs. inline . always ( )
460- && let ( Some ( no_sanitize_span ) , Some ( inline_span) ) =
461+ && let ( Some ( sanitize_span ) , Some ( inline_span) ) =
461462 ( interesting_spans. sanitize , interesting_spans. inline )
462463 {
463464 let hir_id = tcx. local_def_id_to_hir_id ( did) ;
464- tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, no_sanitize_span , |lint| {
465- lint. primary_message ( "setting `sanitize` off will have no effect after inlining" ) ;
465+ tcx. node_span_lint ( lint:: builtin:: INLINE_NO_SANITIZE , hir_id, sanitize_span , |lint| {
466+ lint. primary_message ( "non-default `sanitize` will have no effect after inlining" ) ;
466467 lint. span_note ( inline_span, "inlining requested here" ) ;
467468 } )
468469 }
469470
471+ // warn for nonblocking async fn.
472+ // This doesn't behave as expected, because the executor can run blocking code without the sanitizer noticing.
473+ if codegen_fn_attrs. sanitizers . rtsan_setting == RtsanSetting :: Nonblocking
474+ && let Some ( sanitize_span) = interesting_spans. sanitize
475+ // async function
476+ && ( tcx. asyncness ( did) . is_async ( ) || ( tcx. is_closure_like ( did. into ( ) )
477+ // async block
478+ && ( tcx. coroutine_is_async ( did. into ( ) )
479+ // async closure
480+ || tcx. coroutine_is_async ( tcx. coroutine_for_closure ( did) ) ) ) )
481+ {
482+ let hir_id = tcx. local_def_id_to_hir_id ( did) ;
483+ tcx. node_span_lint (
484+ lint:: builtin:: RTSAN_NONBLOCKING_ASYNC ,
485+ hir_id,
486+ sanitize_span,
487+ |lint| {
488+ lint. primary_message ( r#"the async executor can run blocking code, without realtime sanitizer catching it"# ) ;
489+ }
490+ ) ;
491+ }
492+
470493 // error when specifying link_name together with link_ordinal
471494 if let Some ( _) = codegen_fn_attrs. symbol_name
472495 && let Some ( _) = codegen_fn_attrs. link_ordinal
@@ -576,30 +599,35 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
576599 codegen_fn_attrs
577600}
578601
579- fn disabled_sanitizers_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerSet {
602+ fn sanitizer_settings_for ( tcx : TyCtxt < ' _ > , did : LocalDefId ) -> SanitizerFnAttrs {
580603 // Backtrack to the crate root.
581- let mut disabled = match tcx. opt_local_parent ( did) {
604+ let mut settings = match tcx. opt_local_parent ( did) {
582605 // Check the parent (recursively).
583- Some ( parent) => tcx. disabled_sanitizers_for ( parent) ,
606+ Some ( parent) => tcx. sanitizer_settings_for ( parent) ,
584607 // We reached the crate root without seeing an attribute, so
585608 // there is no sanitizers to exclude.
586- None => SanitizerSet :: empty ( ) ,
609+ None => SanitizerFnAttrs :: default ( ) ,
587610 } ;
588611
589612 // Check for a sanitize annotation directly on this def.
590- if let Some ( ( on_set, off_set) ) = find_attr ! ( tcx. get_all_attrs( did) , AttributeKind :: Sanitize { on_set, off_set, ..} => ( on_set, off_set) )
613+ if let Some ( ( on_set, off_set, rtsan ) ) = find_attr ! ( tcx. get_all_attrs( did) , AttributeKind :: Sanitize { on_set, off_set, rtsan , ..} => ( on_set, off_set, rtsan ) )
591614 {
592615 // the on set is the set of sanitizers explicitly enabled.
593616 // we mask those out since we want the set of disabled sanitizers here
594- disabled &= !* on_set;
617+ settings . disabled &= !* on_set;
595618 // the off set is the set of sanitizers explicitly disabled.
596619 // we or those in here.
597- disabled |= * off_set;
620+ settings . disabled |= * off_set;
598621 // the on set and off set are distjoint since there's a third option: unset.
599622 // a node may not set the sanitizer setting in which case it inherits from parents.
600623 // the code above in this function does this backtracking
624+
625+ // if rtsan was specified here override the parent
626+ if let Some ( rtsan) = rtsan {
627+ settings. rtsan_setting = * rtsan;
628+ }
601629 }
602- disabled
630+ settings
603631}
604632
605633/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
@@ -731,7 +759,7 @@ pub(crate) fn provide(providers: &mut Providers) {
731759 codegen_fn_attrs,
732760 should_inherit_track_caller,
733761 inherited_align,
734- disabled_sanitizers_for ,
762+ sanitizer_settings_for ,
735763 ..* providers
736764 } ;
737765}
0 commit comments