Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API soundness issues #2

Open
steffahn opened this issue Feb 20, 2025 · 0 comments
Open

API soundness issues #2

steffahn opened this issue Feb 20, 2025 · 0 comments

Comments

@steffahn
Copy link

Implied bounds from non-static T in Parc<T>::project

use pared::sync::Parc;

fn main() {
    let s = "Hello World!".to_owned();
    let x = Parc::new(&());
    let x = x.project(|_| s.as_str()); // why this works?
                                       // even though there are seemingly so many
                                       // 'static bounds already?
                                       // here's a short explanation:

    // it first coerces the Parc<&'static ()> to some Parc<&'short ()>,
    // and then the callback to project, for<'a> FnOnce(&'a &'short ()) -> &'a str
    // is only required to be able to handle any lifetime `'a` with `'short: 'a`
    // which is fine as long as `'short` is shorter than up to the point `s` drops

    println!("{:?}", &*x); // "Hello World!"
    drop(s);
    println!("{:?}", &*x); // garbage / use-after-free
}

A possible fix I could imagine is adding T: 'static to project.

This issue is – very roughly – inspired by Kimundi/owning-ref-rs#71

Dropping of non-'static content through Parc::from_arc

This is probably just clearly missing the U: 'static, since… this just works:

use pared::sync::Parc;
use std::sync::Arc;

struct PrintOnDrop<'a>(&'a str);
impl Drop for PrintOnDrop<'_> {
    fn drop(&mut self) {
        println!("dropping: {:?}", self.0);
    }
}

fn main() {
    let s = "Hello World!".to_owned();
    let arc = Arc::new(PrintOnDrop(&s));
    let p = Parc::from_arc(&arc, |_| &());
    drop(arc);
    drop(s);
    // finally
    drop(p); // garbage / use-after-free

    // type being Parc<()> means this is a type
    // that doesn't have any lifetime restrictions anymore
    // i.e. this can still be used/dropped AFTER `s` is gone,
    // without complaints from the compiler
}

The same applies to Prc and to try_ variants of the APIs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant