From 72519f2161672a2edcd393a41f9f2cd01eddc22f Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Sun, 4 Dec 2022 16:43:07 -0300 Subject: Use a wrapper struct to enable closures --- tests/trybuild.rs | 5 ++++ tests/ui/example_need_cell.rs | 12 ++++++++++ tests/ui/example_need_cell.stderr | 5 ++++ tests/ui/example_opaque_vs_drop.rs | 25 +++++++++++++++++++ tests/ui/example_opaque_vs_drop.stderr | 15 ++++++++++++ tests/ui/no_uaf_1.rs | 44 ++++++++++++++++++++++++++++++++++ tests/ui/no_uaf_1.stderr | 37 ++++++++++++++++++++++++++++ 7 files changed, 143 insertions(+) create mode 100644 tests/trybuild.rs create mode 100644 tests/ui/example_need_cell.rs create mode 100644 tests/ui/example_need_cell.stderr create mode 100644 tests/ui/example_opaque_vs_drop.rs create mode 100644 tests/ui/example_opaque_vs_drop.stderr create mode 100644 tests/ui/no_uaf_1.rs create mode 100644 tests/ui/no_uaf_1.stderr (limited to 'tests') diff --git a/tests/trybuild.rs b/tests/trybuild.rs new file mode 100644 index 0000000..870c2f9 --- /dev/null +++ b/tests/trybuild.rs @@ -0,0 +1,5 @@ +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/tests/ui/example_need_cell.rs b/tests/ui/example_need_cell.rs new file mode 100644 index 0000000..b6e12eb --- /dev/null +++ b/tests/ui/example_need_cell.rs @@ -0,0 +1,12 @@ +//! Example of how Rust requires the use of a Cell to build a self-referential +//! struct. +//! +//! NOTE: Also in top-level crate documentation. Keep 'em in sync. + +struct MySelfRefStruct<'this> { + this: &'this MySelfRefStruct<'this>, +} + +fn main() { + let x = MySelfRefStruct { this: &x }; +} diff --git a/tests/ui/example_need_cell.stderr b/tests/ui/example_need_cell.stderr new file mode 100644 index 0000000..a01c9ae --- /dev/null +++ b/tests/ui/example_need_cell.stderr @@ -0,0 +1,5 @@ +error[E0425]: cannot find value `x` in this scope + --> tests/ui/example_need_cell.rs:11:38 + | +11 | let x = MySelfRefStruct { this: &x }; + | ^ not found in this scope diff --git a/tests/ui/example_opaque_vs_drop.rs b/tests/ui/example_opaque_vs_drop.rs new file mode 100644 index 0000000..b2c1809 --- /dev/null +++ b/tests/ui/example_opaque_vs_drop.rs @@ -0,0 +1,25 @@ +//! Example of how `opaque!` prevents unsound `Drop`. +//! +//! NOTE: Also in trait `Opaque` documentation. Keep 'em in sync. + +use std::cell::Cell; +use selfref::opaque; + +struct Foo<'a> { + foo: Cell>>, +} + +impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + } +} + +struct FooKey; +opaque! { + impl Opaque for FooKey { + type Kind<'a> = Foo<'a>; + } +} + +fn main() { +} diff --git a/tests/ui/example_opaque_vs_drop.stderr b/tests/ui/example_opaque_vs_drop.stderr new file mode 100644 index 0000000..1749031 --- /dev/null +++ b/tests/ui/example_opaque_vs_drop.stderr @@ -0,0 +1,15 @@ +error[E0597]: `x` does not live long enough + --> tests/ui/example_opaque_vs_drop.rs:18:1 + | +18 | / opaque! { +19 | | impl Opaque for FooKey { +20 | | type Kind<'a> = Foo<'a>; +21 | | } +22 | | } + | | ^ + | | | + | | borrowed value does not live long enough + | |_`x` dropped here while still borrowed + | borrow might be used here, when `x` is dropped and runs the destructor for type `UBCheck>` + | + = note: this error originates in the macro `opaque` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/no_uaf_1.rs b/tests/ui/no_uaf_1.rs new file mode 100644 index 0000000..e4d7ac4 --- /dev/null +++ b/tests/ui/no_uaf_1.rs @@ -0,0 +1,44 @@ +use core::cell::Cell; + +use selfref::Holder; +use selfref::NewWith; +use selfref::opaque; + +mod bad { + use super::*; + use std::rc::Rc; + struct Foo<'a> { + x: String, + y: Rc>, + } + struct FooOpaque; + opaque! { + impl Opaque for FooOpaque { + type Kind<'a> = Foo<'a>; + } + } + pub fn test() { + let rc = Rc::new(Cell::new("")); + struct FooBuilder<'b>(Rc>); + impl<'k, 'b> NewWith<'k, FooOpaque> for FooBuilder<'b> { + fn new_with<'a>(self) -> Foo<'a> where 'k: 'a { + Foo { + x: "Hello".to_owned(), + y: self.0, + } + } + } + let x = Holder::new_with(FooBuilder(rc.clone())); + let x = Box::pin(x); + x.as_ref().operate_in(|foo| { + let foo = foo.get_ref(); + foo.y.set(&foo.x); + }); + dbg!(&rc); + drop(x); + dbg!(&rc); + } +} +fn main() { + bad::test(); +} diff --git a/tests/ui/no_uaf_1.stderr b/tests/ui/no_uaf_1.stderr new file mode 100644 index 0000000..6db82ed --- /dev/null +++ b/tests/ui/no_uaf_1.stderr @@ -0,0 +1,37 @@ +error: lifetime may not live long enough + --> tests/ui/no_uaf_1.rs:25:17 + | +23 | impl<'k, 'b> NewWith<'k, FooOpaque> for FooBuilder<'b> { + | -- lifetime `'b` defined here +24 | fn new_with<'a>(self) -> Foo<'a> where 'k: 'a { + | -- lifetime `'a` defined here +25 | / Foo { +26 | | x: "Hello".to_owned(), +27 | | y: self.0, +28 | | } + | |_________________^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Foo<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +error: lifetime may not live long enough + --> tests/ui/no_uaf_1.rs:25:17 + | +23 | impl<'k, 'b> NewWith<'k, FooOpaque> for FooBuilder<'b> { + | -- lifetime `'b` defined here +24 | fn new_with<'a>(self) -> Foo<'a> where 'k: 'a { + | -- lifetime `'a` defined here +25 | / Foo { +26 | | x: "Hello".to_owned(), +27 | | y: self.0, +28 | | } + | |_________________^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Foo<'a>` is invariant over the parameter `'a` + = help: see for more information about variance + +help: `'b` and `'a` must be the same: replace one with the other -- cgit 1.4.1