]> git.lizzy.rs Git - rust.git/commitdiff
Add tests for #62211
authorJonas Schievink <jonasschievink@gmail.com>
Fri, 28 Jun 2019 22:30:35 +0000 (00:30 +0200)
committerJonas Schievink <jonasschievink@gmail.com>
Fri, 21 Feb 2020 18:41:22 +0000 (19:41 +0100)
src/test/ui/associated-types/defaults-unsound-62211-1.rs [new file with mode: 0644]
src/test/ui/associated-types/defaults-unsound-62211-1.stderr [new file with mode: 0644]
src/test/ui/associated-types/defaults-unsound-62211-2.rs [new file with mode: 0644]
src/test/ui/associated-types/defaults-unsound-62211-2.stderr [new file with mode: 0644]

diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs
new file mode 100644 (file)
index 0000000..aa7beca
--- /dev/null
@@ -0,0 +1,62 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/62211
+//!
+//! The old implementation of defaults did not check whether the provided
+//! default actually fulfills all bounds on the assoc. type, leading to
+//! unsoundness, demonstrated here as a use-after-free.
+
+// compile-fail
+
+#![feature(associated_type_defaults)]
+
+use std::{
+    fmt::Display,
+    ops::{AddAssign, Deref}
+};
+
+
+trait UncheckedCopy: Sized {
+    // This Output is said to be Copy. Yet we default to Self
+    // and it's accepted, not knowing if Self ineed is Copy
+    type Output: Copy
+    //~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied
+    + Deref<Target = str>
+    //~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied
+    + AddAssign<&'static str>
+    //~^ ERROR cannot add-assign `&'static str` to `Self`
+    + From<Self>
+    + Display = Self;
+    //~^ ERROR `Self` doesn't implement `std::fmt::Display`
+
+    // We said the Output type was Copy, so we can Copy it freely!
+    fn unchecked_copy(other: &Self::Output) -> Self::Output {
+        (*other)
+    }
+
+    fn make_origin(s: Self) -> Self::Output {
+        s.into()
+    }
+}
+
+impl<T> UncheckedCopy for T {}
+//~^ ERROR `T` doesn't implement `std::fmt::Display`
+//~| ERROR the trait bound `T: std::ops::Deref` is not satisfied
+//~| ERROR cannot add-assign `&'static str` to `T`
+//~| ERROR the trait bound `T: std::marker::Copy` is not satisfied
+
+fn bug<T: UncheckedCopy>(origin: T) {
+    let origin = T::make_origin(origin);
+    let mut copy = T::unchecked_copy(&origin);
+
+    // assert we indeed have 2 strings pointing to the same buffer.
+    assert_eq!(origin.as_ptr(), copy.as_ptr());
+
+    // Drop the origin. Any use of `copy` is UB.
+    drop(origin);
+
+    copy += "This is invalid!";
+    println!("{}", copy);
+}
+
+fn main() {
+    bug(String::from("hello!"));
+}
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr
new file mode 100644 (file)
index 0000000..417edd8
--- /dev/null
@@ -0,0 +1,93 @@
+error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
+  --> $DIR/defaults-unsound-62211-1.rs:20:18
+   |
+LL |     type Output: Copy
+   |                  ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: std::marker::Copy` bound
+note: required by `UncheckedCopy`
+  --> $DIR/defaults-unsound-62211-1.rs:17:1
+   |
+LL | trait UncheckedCopy: Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: cannot add-assign `&'static str` to `Self`
+  --> $DIR/defaults-unsound-62211-1.rs:24:7
+   |
+LL |     + AddAssign<&'static str>
+   |       ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
+   |
+   = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self`
+   = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound
+note: required by `UncheckedCopy`
+  --> $DIR/defaults-unsound-62211-1.rs:17:1
+   |
+LL | trait UncheckedCopy: Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
+  --> $DIR/defaults-unsound-62211-1.rs:22:7
+   |
+LL |     + Deref<Target = str>
+   |       ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: std::ops::Deref` bound
+note: required by `UncheckedCopy`
+  --> $DIR/defaults-unsound-62211-1.rs:17:1
+   |
+LL | trait UncheckedCopy: Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `Self` doesn't implement `std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-1.rs:27:7
+   |
+LL |     + Display = Self;
+   |       ^^^^^^^ `Self` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `Self`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = help: consider adding a `where Self: std::fmt::Display` bound
+note: required by `UncheckedCopy`
+  --> $DIR/defaults-unsound-62211-1.rs:17:1
+   |
+LL | trait UncheckedCopy: Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-1.rs:40:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `T`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = help: consider adding a `where T: std::fmt::Display` bound
+
+error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied
+  --> $DIR/defaults-unsound-62211-1.rs:40:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::ops::Deref` bound
+
+error[E0277]: cannot add-assign `&'static str` to `T`
+  --> $DIR/defaults-unsound-62211-1.rs:40:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ no implementation for `T += &'static str`
+   |
+   = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T`
+   = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/defaults-unsound-62211-1.rs:40:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs
new file mode 100644 (file)
index 0000000..ce12bd4
--- /dev/null
@@ -0,0 +1,62 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/62211
+//!
+//! The old implementation of defaults did not check whether the provided
+//! default actually fulfills all bounds on the assoc. type, leading to
+//! unsoundness and ICEs, the latter being demonstrated here.
+
+// compile-fail
+
+#![feature(associated_type_defaults)]
+
+use std::{
+    fmt::Display,
+    ops::{AddAssign, Deref}
+};
+
+
+trait UncheckedCopy: Sized {
+    // This Output is said to be Copy. Yet we default to Self
+    // and it's accepted, not knowing if Self ineed is Copy
+    type Output: Copy
+    //~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied
+    + Deref<Target = str>
+    //~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied
+    + AddAssign<&'static str>
+    //~^ ERROR cannot add-assign `&'static str` to `Self`
+    + From<Self>
+    + Display = Self;
+    //~^ ERROR `Self` doesn't implement `std::fmt::Display`
+
+    // We said the Output type was Copy, so we can Copy it freely!
+    fn unchecked_copy(other: &Self::Output) -> Self::Output {
+        (*other)
+    }
+
+    fn make_origin(s: Self) -> Self::Output {
+        s.into()
+    }
+}
+
+impl<T> UncheckedCopy for T {}
+//~^ ERROR `T` doesn't implement `std::fmt::Display`
+//~| ERROR the trait bound `T: std::ops::Deref` is not satisfied
+//~| ERROR cannot add-assign `&'static str` to `T`
+//~| ERROR the trait bound `T: std::marker::Copy` is not satisfied
+
+fn bug<T: UncheckedCopy>(origin: T) {
+    let origin = T::make_origin(origin);
+    let mut copy = T::unchecked_copy(&origin);
+
+    // assert we indeed have 2 strings pointing to the same buffer.
+    assert_eq!(origin.as_ptr(), copy.as_ptr());
+
+    // Drop the origin. Any use of `copy` is UB.
+    drop(origin);
+
+    copy += "This is invalid!";
+    println!("{}", copy);
+}
+
+fn main() {
+    bug(());
+}
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr
new file mode 100644 (file)
index 0000000..a1ce1f6
--- /dev/null
@@ -0,0 +1,93 @@
+error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
+  --> $DIR/defaults-unsound-62211-2.rs:20:18
+   |
+LL |     type Output: Copy
+   |                  ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: std::marker::Copy` bound
+note: required by `UncheckedCopy`
+  --> $DIR/defaults-unsound-62211-2.rs:17:1
+   |
+LL | trait UncheckedCopy: Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: cannot add-assign `&'static str` to `Self`
+  --> $DIR/defaults-unsound-62211-2.rs:24:7
+   |
+LL |     + AddAssign<&'static str>
+   |       ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
+   |
+   = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self`
+   = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound
+note: required by `UncheckedCopy`
+  --> $DIR/defaults-unsound-62211-2.rs:17:1
+   |
+LL | trait UncheckedCopy: Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
+  --> $DIR/defaults-unsound-62211-2.rs:22:7
+   |
+LL |     + Deref<Target = str>
+   |       ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
+   |
+   = help: consider adding a `where Self: std::ops::Deref` bound
+note: required by `UncheckedCopy`
+  --> $DIR/defaults-unsound-62211-2.rs:17:1
+   |
+LL | trait UncheckedCopy: Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `Self` doesn't implement `std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-2.rs:27:7
+   |
+LL |     + Display = Self;
+   |       ^^^^^^^ `Self` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `Self`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = help: consider adding a `where Self: std::fmt::Display` bound
+note: required by `UncheckedCopy`
+  --> $DIR/defaults-unsound-62211-2.rs:17:1
+   |
+LL | trait UncheckedCopy: Sized {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+  --> $DIR/defaults-unsound-62211-2.rs:40:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `T`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+   = help: consider adding a `where T: std::fmt::Display` bound
+
+error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied
+  --> $DIR/defaults-unsound-62211-2.rs:40:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::ops::Deref` bound
+
+error[E0277]: cannot add-assign `&'static str` to `T`
+  --> $DIR/defaults-unsound-62211-2.rs:40:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ no implementation for `T += &'static str`
+   |
+   = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T`
+   = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/defaults-unsound-62211-2.rs:40:9
+   |
+LL | impl<T> UncheckedCopy for T {}
+   |         ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = help: consider adding a `where T: std::marker::Copy` bound
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.