about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/test/ui/issue-27282-mutate-before-diverging-arm-1.rs43
-rw-r--r--src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr25
-rw-r--r--src/test/ui/issue-27282-mutate-before-diverging-arm-2.rs52
-rw-r--r--src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr26
4 files changed, 146 insertions, 0 deletions
diff --git a/src/test/ui/issue-27282-mutate-before-diverging-arm-1.rs b/src/test/ui/issue-27282-mutate-before-diverging-arm-1.rs
new file mode 100644
index 00000000000..b575f4ebce6
--- /dev/null
+++ b/src/test/ui/issue-27282-mutate-before-diverging-arm-1.rs
@@ -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"),
+    }
+}
diff --git a/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr b/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr
new file mode 100644
index 00000000000..8f7fe9d33fe
--- /dev/null
+++ b/src/test/ui/issue-27282-mutate-before-diverging-arm-1.stderr
@@ -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`.
diff --git a/src/test/ui/issue-27282-mutate-before-diverging-arm-2.rs b/src/test/ui/issue-27282-mutate-before-diverging-arm-2.rs
new file mode 100644
index 00000000000..866fed13685
--- /dev/null
+++ b/src/test/ui/issue-27282-mutate-before-diverging-arm-2.rs
@@ -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"),
+    }
+}
diff --git a/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr b/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr
new file mode 100644
index 00000000000..df5e4300cec
--- /dev/null
+++ b/src/test/ui/issue-27282-mutate-before-diverging-arm-2.stderr
@@ -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`.