Skip to content

Commit e4c151b

Browse files
committed
add warning for async
1 parent c91e1d8 commit e4c151b

File tree

4 files changed

+66
-11
lines changed

4 files changed

+66
-11
lines changed

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::str::FromStr;
33
use rustc_abi::{Align, ExternAbi};
44
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
55
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
6-
use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, UsedBy, RtsanSetting};
6+
use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, RtsanSetting, UsedBy};
77
use rustc_hir::def::DefKind;
88
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
99
use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items};
@@ -470,6 +470,19 @@ fn check_result(
470470
})
471471
}
472472

473+
// warn for nonblocking async fn.
474+
// This doesn't behave as expected, because the executor can run blocking code without the sanitizer noticing.
475+
if codegen_fn_attrs.sanitizers.rtsan_setting == RtsanSetting::Nonblocking
476+
&& tcx.asyncness(did).is_async()
477+
&& let Some(sanitize_span) = interesting_spans.sanitize
478+
{
479+
//tcx.dcx().span_err(sanitize_span, r#"Using `#[sanitize(realtime = "nonblocking")]` is not supported for async functions"#);
480+
let hir_id = tcx.local_def_id_to_hir_id(did);
481+
tcx.node_span_lint(lint::builtin::RTSAN_NONBLOCKING_ASYNC, hir_id, sanitize_span, |lint| {
482+
lint.primary_message(r#"the async executor can run blocking code, without realtime sanitizer catching it"#);
483+
});
484+
}
485+
473486
// error when specifying link_name together with link_ordinal
474487
if let Some(_) = codegen_fn_attrs.symbol_name
475488
&& let Some(_) = codegen_fn_attrs.link_ordinal

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ declare_lint_pass! {
8787
REFINING_IMPL_TRAIT_REACHABLE,
8888
RENAMED_AND_REMOVED_LINTS,
8989
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
90+
RTSAN_NONBLOCKING_ASYNC,
9091
RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
9192
RUST_2021_INCOMPATIBLE_OR_PATTERNS,
9293
RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
@@ -2332,6 +2333,35 @@ declare_lint! {
23322333
r#"detects incompatible use of `#[inline(always)]` and `#[sanitize(... = "off")]`"#,
23332334
}
23342335

2336+
declare_lint! {
2337+
/// The `rtsan_nonblocking_async` lint detects incompatible use of
2338+
/// [`#[sanitize(realtime = "nonblocking")]`][sanitize] on async functions.
2339+
///
2340+
/// [sanitize]: https://doc.rust-lang.org/nightly/unstable-book/language-features/no-sanitize.html
2341+
/// ### Example
2342+
///
2343+
/// ```rust
2344+
/// #![feature(sanitize)]
2345+
///
2346+
/// #[sanitize(realtime = "nonblocking")]
2347+
/// async fn x() {}
2348+
///
2349+
/// fn main() {
2350+
/// x()
2351+
/// }
2352+
/// ```
2353+
///
2354+
/// {{produces}}
2355+
///
2356+
/// ### Explanation
2357+
///
2358+
/// The sanitizer only considers the async function body nonblocking. The executor, which runs on
2359+
/// every `.await` point can run non-realtime code, without the sanitizer catching it.
2360+
pub RTSAN_NONBLOCKING_ASYNC,
2361+
Warn,
2362+
r#"detects incompatible uses of `#[sanitize(realtime = "nonblocking")]` on async functions"#,
2363+
}
2364+
23352365
declare_lint! {
23362366
/// The `asm_sub_register` lint detects using only a subset of a register
23372367
/// for inline asm inputs.

tests/ui/sanitize-attr/invalid-sanitize.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//@ edition:2018
12
#![feature(sanitize)]
23

34
#[sanitize(brontosaurus = "off")] //~ ERROR malformed `sanitize` attribute input
@@ -22,3 +23,6 @@ fn just_word() {}
2223

2324
#[sanitize(realtime = "on")] //~ ERROR malformed `sanitize` attribute input
2425
fn wrong_value_realtime() {}
26+
27+
#[sanitize(realtime = "nonblocking")] //~ WARN: the async executor can run blocking code, without realtime sanitizer catching it [rtsan_nonblocking_async]
28+
async fn async_nonblocking() {}

tests/ui/sanitize-attr/invalid-sanitize.stderr

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0539]: malformed `sanitize` attribute input
2-
--> $DIR/invalid-sanitize.rs:3:1
2+
--> $DIR/invalid-sanitize.rs:4:1
33
|
44
LL | #[sanitize(brontosaurus = "off")]
55
| ^^^^^^^^^^^------------^^^^^^^^^^
@@ -23,31 +23,31 @@ LL + #[sanitize(kcfi = "on|off")]
2323
= and 6 other candidates
2424

2525
error: multiple `sanitize` attributes
26-
--> $DIR/invalid-sanitize.rs:6:1
26+
--> $DIR/invalid-sanitize.rs:7:1
2727
|
2828
LL | #[sanitize(address = "off")]
2929
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
3030
|
3131
note: attribute also specified here
32-
--> $DIR/invalid-sanitize.rs:7:1
32+
--> $DIR/invalid-sanitize.rs:8:1
3333
|
3434
LL | #[sanitize(address = "off")]
3535
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3636

3737
error: multiple `sanitize` attributes
38-
--> $DIR/invalid-sanitize.rs:10:1
38+
--> $DIR/invalid-sanitize.rs:11:1
3939
|
4040
LL | #[sanitize(address = "on")]
4141
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
4242
|
4343
note: attribute also specified here
44-
--> $DIR/invalid-sanitize.rs:11:1
44+
--> $DIR/invalid-sanitize.rs:12:1
4545
|
4646
LL | #[sanitize(address = "off")]
4747
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4848

4949
error[E0539]: malformed `sanitize` attribute input
50-
--> $DIR/invalid-sanitize.rs:14:1
50+
--> $DIR/invalid-sanitize.rs:15:1
5151
|
5252
LL | #[sanitize(address = "bogus")]
5353
| ^^^^^^^^^^^^^^^^^^^^^-------^^
@@ -71,7 +71,7 @@ LL + #[sanitize(kcfi = "on|off")]
7171
= and 6 other candidates
7272

7373
error[E0539]: malformed `sanitize` attribute input
74-
--> $DIR/invalid-sanitize.rs:17:1
74+
--> $DIR/invalid-sanitize.rs:18:1
7575
|
7676
LL | #[sanitize = "off"]
7777
| ^^^^^^^^^^^^^^^^^^^ expected this to be a list
@@ -93,7 +93,7 @@ LL + #[sanitize(kcfi = "on|off")]
9393
= and 6 other candidates
9494

9595
error[E0539]: malformed `sanitize` attribute input
96-
--> $DIR/invalid-sanitize.rs:20:1
96+
--> $DIR/invalid-sanitize.rs:21:1
9797
|
9898
LL | #[sanitize]
9999
| ^^^^^^^^^^^ expected this to be a list
@@ -111,7 +111,7 @@ LL | #[sanitize(kcfi = "on|off")]
111111
= and 6 other candidates
112112

113113
error[E0539]: malformed `sanitize` attribute input
114-
--> $DIR/invalid-sanitize.rs:23:1
114+
--> $DIR/invalid-sanitize.rs:24:1
115115
|
116116
LL | #[sanitize(realtime = "on")]
117117
| ^^^^^^^^^^^^^^^^^^^^^^----^^
@@ -134,6 +134,14 @@ LL + #[sanitize(kcfi = "on|off")]
134134
|
135135
= and 6 other candidates
136136

137-
error: aborting due to 7 previous errors
137+
warning: the async executor can run blocking code, without realtime sanitizer catching it
138+
--> $DIR/invalid-sanitize.rs:27:1
139+
|
140+
LL | #[sanitize(realtime = "nonblocking")]
141+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
142+
|
143+
= note: `#[warn(rtsan_nonblocking_async)]` on by default
144+
145+
error: aborting due to 7 previous errors; 1 warning emitted
138146

139147
For more information about this error, try `rustc --explain E0539`.

0 commit comments

Comments
 (0)