-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Review feedback: Adding test cases suggested by arielb1.
- Loading branch information
Showing
4 changed files
with
146 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
// This is testing an attempt to corrupt the discriminant of the match | ||
// arm in a guard, followed by an attempt to continue matching on that | ||
// corrupted discriminant in the remaining match arms. | ||
// | ||
// Basically this is testing that our new NLL feature of emitting a | ||
// fake read on each match arm is catching cases like this. | ||
// | ||
// This case is interesting because it includes a guard that | ||
// diverges, and therefore a single final fake-read at the very end | ||
// after the final match arm would not suffice. | ||
|
||
#![feature(nll)] | ||
|
||
struct ForceFnOnce; | ||
|
||
fn main() { | ||
let mut x = &mut Some(&2); | ||
let force_fn_once = ForceFnOnce; | ||
match x { | ||
&mut None => panic!("unreachable"), | ||
&mut Some(&_) if { | ||
// ForceFnOnce needed to exploit #27282 | ||
(|| { *x = None; drop(force_fn_once); })(); | ||
//~^ ERROR closure requires unique access to `x` but it is already borrowed [E0500] | ||
false | ||
} => {} | ||
&mut Some(&a) if { // this binds to garbage if we've corrupted discriminant | ||
println!("{}", a); | ||
panic!() | ||
} => {} | ||
_ => panic!("unreachable"), | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr
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,25 @@ | ||
error[E0500]: closure requires unique access to `x` but it is already borrowed | ||
--> $DIR/issue-27282-mutate-before-diverging-arm-1.rs:33:14 | ||
| | ||
LL | match x { | ||
| _____- | ||
| |_____| | ||
| || | ||
LL | || &mut None => panic!("unreachable"), | ||
LL | || &mut Some(&_) if { | ||
LL | || // ForceFnOnce needed to exploit #27282 | ||
LL | || (|| { *x = None; drop(force_fn_once); })(); | ||
| || ^^ - borrow occurs due to use of `x` in closure | ||
| || | | ||
| || closure construction occurs here | ||
... || | ||
LL | || _ => panic!("unreachable"), | ||
LL | || } | ||
| || - | ||
| ||_____| | ||
| |______borrow occurs here | ||
| borrow later used here | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0500`. |
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,52 @@ | ||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
// This is testing an attempt to corrupt the discriminant of the match | ||
// arm in a guard, followed by an attempt to continue matching on that | ||
// corrupted discriminant in the remaining match arms. | ||
// | ||
// Basically this is testing that our new NLL feature of emitting a | ||
// fake read on each match arm is catching cases like this. | ||
// | ||
// This case is interesting because it includes a guard that | ||
// diverges, and therefore a single final fake-read at the very end | ||
// after the final match arm would not suffice. | ||
// | ||
// It is also interesting because the access to the corrupted data | ||
// occurs in the pattern-match itself, and not in the guard | ||
// expression. | ||
|
||
#![feature(nll)] | ||
|
||
struct ForceFnOnce; | ||
|
||
fn main() { | ||
let mut x = &mut Some(&2); | ||
let force_fn_once = ForceFnOnce; | ||
match x { | ||
&mut None => panic!("unreachable"), | ||
&mut Some(&_) | ||
if { | ||
// ForceFnOnce needed to exploit #27282 | ||
(|| { *x = None; drop(force_fn_once); })(); | ||
//~^ ERROR closure requires unique access to `x` but it is already borrowed [E0500] | ||
false | ||
} => {} | ||
|
||
// this segfaults if we corrupted the discriminant, because | ||
// the compiler gets to *assume* that it cannot be the `None` | ||
// case, even though that was the effect of the guard. | ||
&mut Some(&2) | ||
if { | ||
panic!() | ||
} => {} | ||
_ => panic!("unreachable"), | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr
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,26 @@ | ||
error[E0500]: closure requires unique access to `x` but it is already borrowed | ||
--> $DIR/issue-27282-mutate-before-diverging-arm-2.rs:38:18 | ||
| | ||
LL | match x { | ||
| _____- | ||
| |_____| | ||
| || | ||
LL | || &mut None => panic!("unreachable"), | ||
LL | || &mut Some(&_) | ||
LL | || if { | ||
LL | || // ForceFnOnce needed to exploit #27282 | ||
LL | || (|| { *x = None; drop(force_fn_once); })(); | ||
| || ^^ - borrow occurs due to use of `x` in closure | ||
| || | | ||
| || closure construction occurs here | ||
... || | ||
LL | || _ => panic!("unreachable"), | ||
LL | || } | ||
| || - | ||
| ||_____| | ||
| |______borrow occurs here | ||
| borrow later used here | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0500`. |