gtk-rs-core icon indicating copy to clipboard operation
gtk-rs-core copied to clipboard

Allowing safe construction of unknown enums via the `__Unknown()` variant is potentially unsound

Open sdroege opened this issue 2 years ago • 5 comments

C code that gets such unknown enum values might do anything.

Not sure how we should handle this. Maybe:

#[non_exhaustive]
pub enum Foo {
    A,
    B,
    C,
    Unknown(i32),  // no `pub`!
}

impl Foo {
    pub fn is_unknown(self) -> bool { ... } // I think this is actually unnecessary as you can as well match on it... just not on the contained value
    pub fn value(self) -> i32 { ... }  // also returns unknown values
    pub unsafe fn unknown(value: i32) -> Self { ... }
}

@bilelmoussaoui @GuillaumeGomez What do you think?

sdroege avatar Nov 07 '22 09:11 sdroege

No pub wouldn't change anything on an enum variant (unless you meant #[doc(hidden)]? But otherwise I think it's a good idea.

GuillaumeGomez avatar Nov 07 '22 10:11 GuillaumeGomez

If the field in the enum variant is not public then you can't construct it, and you can't match on its content either.

sdroege avatar Nov 07 '22 10:11 sdroege

Unless I missed something, this code works:

mod whatever {
    pub enum Foo {
        What,
        Bar(i32),
    }
}

fn main() {
    // you can build it
    let x = whatever::Foo::Bar(0);
    match x {
        whatever::Foo::What => {}
        // you can match on it
        whatever::Foo::Bar(i) => {}
    }
}

Only fields of unions and structs can be private.

GuillaumeGomez avatar Nov 07 '22 10:11 GuillaumeGomez

Oh indeed. Well, we can make it a Unknown(UnknownEnumValue) and that type contains the value.

sdroege avatar Nov 07 '22 10:11 sdroege

That sounds good, and then UnknownEnumValue can have an unsafe constructor

jf2048 avatar Nov 07 '22 15:11 jf2048