Skip to content

Commit 9d5cdc9

Browse files
committed
Review feedback: Adding test cases suggested by arielb1.
1 parent 324ced8 commit 9d5cdc9

4 files changed

+146
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This is testing an attempt to corrupt the discriminant of the match
12+
// arm in a guard, followed by an attempt to continue matching on that
13+
// corrupted discriminant in the remaining match arms.
14+
//
15+
// Basically this is testing that our new NLL feature of emitting a
16+
// fake read on each match arm is catching cases like this.
17+
//
18+
// This case is interesting because it includes a guard that
19+
// diverges, and therefore a single final fake-read at the very end
20+
// after the final match arm would not suffice.
21+
22+
#![feature(nll)]
23+
24+
struct ForceFnOnce;
25+
26+
fn main() {
27+
let mut x = &mut Some(&2);
28+
let force_fn_once = ForceFnOnce;
29+
match x {
30+
&mut None => panic!("unreachable"),
31+
&mut Some(&_) if {
32+
// ForceFnOnce needed to exploit #27282
33+
(|| { *x = None; drop(force_fn_once); })();
34+
//~^ ERROR closure requires unique access to `x` but it is already borrowed [E0500]
35+
false
36+
} => {}
37+
&mut Some(&a) if { // this binds to garbage if we've corrupted discriminant
38+
println!("{}", a);
39+
panic!()
40+
} => {}
41+
_ => panic!("unreachable"),
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0500]: closure requires unique access to `x` but it is already borrowed
2+
--> $DIR/issue-27282-mutate-before-diverging-arm-1.rs:33:14
3+
|
4+
LL | match x {
5+
| _____-
6+
| |_____|
7+
| ||
8+
LL | || &mut None => panic!("unreachable"),
9+
LL | || &mut Some(&_) if {
10+
LL | || // ForceFnOnce needed to exploit #27282
11+
LL | || (|| { *x = None; drop(force_fn_once); })();
12+
| || ^^ - borrow occurs due to use of `x` in closure
13+
| || |
14+
| || closure construction occurs here
15+
... ||
16+
LL | || _ => panic!("unreachable"),
17+
LL | || }
18+
| || -
19+
| ||_____|
20+
| |______borrow occurs here
21+
| borrow later used here
22+
23+
error: aborting due to previous error
24+
25+
For more information about this error, try `rustc --explain E0500`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This is testing an attempt to corrupt the discriminant of the match
12+
// arm in a guard, followed by an attempt to continue matching on that
13+
// corrupted discriminant in the remaining match arms.
14+
//
15+
// Basically this is testing that our new NLL feature of emitting a
16+
// fake read on each match arm is catching cases like this.
17+
//
18+
// This case is interesting because it includes a guard that
19+
// diverges, and therefore a single final fake-read at the very end
20+
// after the final match arm would not suffice.
21+
//
22+
// It is also interesting because the access to the corrupted data
23+
// occurs in the pattern-match itself, and not in the guard
24+
// expression.
25+
26+
#![feature(nll)]
27+
28+
struct ForceFnOnce;
29+
30+
fn main() {
31+
let mut x = &mut Some(&2);
32+
let force_fn_once = ForceFnOnce;
33+
match x {
34+
&mut None => panic!("unreachable"),
35+
&mut Some(&_)
36+
if {
37+
// ForceFnOnce needed to exploit #27282
38+
(|| { *x = None; drop(force_fn_once); })();
39+
//~^ ERROR closure requires unique access to `x` but it is already borrowed [E0500]
40+
false
41+
} => {}
42+
43+
// this segfaults if we corrupted the discriminant, because
44+
// the compiler gets to *assume* that it cannot be the `None`
45+
// case, even though that was the effect of the guard.
46+
&mut Some(&2)
47+
if {
48+
panic!()
49+
} => {}
50+
_ => panic!("unreachable"),
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error[E0500]: closure requires unique access to `x` but it is already borrowed
2+
--> $DIR/issue-27282-mutate-before-diverging-arm-2.rs:38:18
3+
|
4+
LL | match x {
5+
| _____-
6+
| |_____|
7+
| ||
8+
LL | || &mut None => panic!("unreachable"),
9+
LL | || &mut Some(&_)
10+
LL | || if {
11+
LL | || // ForceFnOnce needed to exploit #27282
12+
LL | || (|| { *x = None; drop(force_fn_once); })();
13+
| || ^^ - borrow occurs due to use of `x` in closure
14+
| || |
15+
| || closure construction occurs here
16+
... ||
17+
LL | || _ => panic!("unreachable"),
18+
LL | || }
19+
| || -
20+
| ||_____|
21+
| |______borrow occurs here
22+
| borrow later used here
23+
24+
error: aborting due to previous error
25+
26+
For more information about this error, try `rustc --explain E0500`.

0 commit comments

Comments
 (0)