Skip to content

Commit e70f9f2

Browse files
committed
add warning for async
1 parent c980a7a commit e70f9f2

File tree

4 files changed

+99
-11
lines changed

4 files changed

+99
-11
lines changed

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 23 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};
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};
@@ -468,6 +468,28 @@ fn check_result(
468468
})
469469
}
470470

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+
471493
// error when specifying link_name together with link_ordinal
472494
if let Some(_) = codegen_fn_attrs.symbol_name
473495
&& 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_NON_ZST_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,no_run
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: 16 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,18 @@ 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() {}
29+
30+
fn test() {
31+
let _async_block = {
32+
#[sanitize(realtime = "nonblocking")] //~ WARN: the async executor can run blocking code, without realtime sanitizer catching it [rtsan_nonblocking_async]
33+
async {}
34+
};
35+
36+
let _async_closure = {
37+
#[sanitize(realtime = "nonblocking")] //~ WARN: the async executor can run blocking code, without realtime sanitizer catching it [rtsan_nonblocking_async]
38+
async || {}
39+
};
40+
}

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

Lines changed: 30 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,26 @@ 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+
warning: the async executor can run blocking code, without realtime sanitizer catching it
146+
--> $DIR/invalid-sanitize.rs:32:9
147+
|
148+
LL | ... #[sanitize(realtime = "nonblocking")]
149+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
150+
151+
warning: the async executor can run blocking code, without realtime sanitizer catching it
152+
--> $DIR/invalid-sanitize.rs:37:9
153+
|
154+
LL | ... #[sanitize(realtime = "nonblocking")]
155+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
156+
157+
error: aborting due to 7 previous errors; 3 warnings emitted
138158

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

0 commit comments

Comments
 (0)