-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of #132151 - compiler-errors:coroutine-resume-outlives, r=spastorino Ensure that resume arg outlives region bound for coroutines When proving that `{Coroutine}: 'region`, we must also prove that the coroutine's resume ty outlives that region as well. See the inline comment. Fixes #132104
- Loading branch information
Showing
5 changed files
with
110 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Regression test for 132104 | ||
|
||
#![feature(coroutine_trait, coroutines)] | ||
|
||
use std::ops::Coroutine; | ||
use std::{thread, time}; | ||
|
||
fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> { | ||
let mut generator = Box::pin({ | ||
#[coroutine] | ||
move |_ctx| { | ||
let ctx: &'not_static str = yield; | ||
yield; | ||
dbg!(ctx); | ||
} | ||
}); | ||
|
||
// exploit: | ||
generator.as_mut().resume(""); | ||
generator.as_mut().resume(s); // <- generator hoards it as `let ctx`. | ||
//~^ ERROR borrowed data escapes outside of function | ||
thread::spawn(move || { | ||
thread::sleep(time::Duration::from_millis(200)); | ||
generator.as_mut().resume(""); // <- resumes from the last `yield`, running `dbg!(ctx)`. | ||
}) | ||
} | ||
|
||
fn main() { | ||
let local = String::from("..."); | ||
let thread = demo(&local); | ||
drop(local); | ||
let _unrelated = String::from("UAF"); | ||
thread.join().unwrap(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
error[E0521]: borrowed data escapes outside of function | ||
--> $DIR/resume-arg-outlives-2.rs:20:5 | ||
| | ||
LL | fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> { | ||
| ----------- - `s` is a reference that is only valid in the function body | ||
| | | ||
| lifetime `'not_static` defined here | ||
... | ||
LL | generator.as_mut().resume(s); // <- generator hoards it as `let ctx`. | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | | ||
| `s` escapes the function body here | ||
| argument requires that `'not_static` must outlive `'static` | ||
|
||
error: aborting due to 1 previous error | ||
|
||
For more information about this error, try `rustc --explain E0521`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// Regression test for 132104 | ||
|
||
#![feature(coroutine_trait, coroutines)] | ||
|
||
use std::ops::Coroutine; | ||
use std::pin::Pin; | ||
|
||
fn demo<'not_static>(s: &'not_static str) -> Pin<Box<impl Coroutine<&'not_static str> + 'static>> { | ||
let mut generator = Box::pin({ | ||
#[coroutine] | ||
move |ctx: &'not_static str| { | ||
yield; | ||
dbg!(ctx); | ||
} | ||
}); | ||
generator.as_mut().resume(s); | ||
generator | ||
//~^ ERROR lifetime may not live long enough | ||
} | ||
|
||
fn main() { | ||
let local = String::from("..."); | ||
let mut coro = demo(&local); | ||
drop(local); | ||
let _unrelated = String::from("UAF"); | ||
coro.as_mut().resume(""); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
error: lifetime may not live long enough | ||
--> $DIR/resume-arg-outlives.rs:17:5 | ||
| | ||
LL | fn demo<'not_static>(s: &'not_static str) -> Pin<Box<impl Coroutine<&'not_static str> + 'static>> { | ||
| ----------- lifetime `'not_static` defined here | ||
... | ||
LL | generator | ||
| ^^^^^^^^^ returning this value requires that `'not_static` must outlive `'static` | ||
| | ||
help: consider changing `impl Coroutine<&'not_static str> + 'static`'s explicit `'static` bound to the lifetime of argument `s` | ||
| | ||
LL | fn demo<'not_static>(s: &'not_static str) -> Pin<Box<impl Coroutine<&'not_static str> + 'not_static>> { | ||
| ~~~~~~~~~~~ | ||
help: alternatively, add an explicit `'static` bound to this reference | ||
| | ||
LL | fn demo<'not_static>(s: &'static str) -> Pin<Box<impl Coroutine<&'not_static str> + 'static>> { | ||
| ~~~~~~~~~~~~ | ||
|
||
error: aborting due to 1 previous error | ||
|