Add tests for #62211
This commit is contained in:
parent
ff5d11e043
commit
07ad64f70f
62
src/test/ui/associated-types/defaults-unsound-62211-1.rs
Normal file
62
src/test/ui/associated-types/defaults-unsound-62211-1.rs
Normal file
@ -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!"));
|
||||
}
|
93
src/test/ui/associated-types/defaults-unsound-62211-1.stderr
Normal file
93
src/test/ui/associated-types/defaults-unsound-62211-1.stderr
Normal file
@ -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`.
|
62
src/test/ui/associated-types/defaults-unsound-62211-2.rs
Normal file
62
src/test/ui/associated-types/defaults-unsound-62211-2.rs
Normal file
@ -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(());
|
||||
}
|
93
src/test/ui/associated-types/defaults-unsound-62211-2.stderr
Normal file
93
src/test/ui/associated-types/defaults-unsound-62211-2.stderr
Normal file
@ -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`.
|
Loading…
Reference in New Issue
Block a user