Skip to content

[UB] CtlType::from(16) builds an invalid enum outside FreeBSD #76

Description

@fereidani

Hey, I've found this while scanning the top downloaded crates with my UB static analyzer.

src/ctl_type.rs:41:

impl std::convert::From<u32> for CtlType {
    fn from(t: u32) -> Self {
        assert!(t <= 16);
        unsafe { std::mem::transmute(t) }
    }
}

The guard allows 16, but discriminant 16 is Temperature, which only exists under #[cfg(target_os = "freebsd")]. On Linux or macOS the valid discriminants stop at 15, so CtlType::from(16) transmutes into a value the enum does not have. It is a safe public conversion, so safe code produces an invalid value.

#[test]
fn ctl_type_from_16_is_invalid_off_freebsd() {
    let t = sysctl::CtlType::from(16u32);
    let _ = format!("{:?}", t);
}
$ cargo +nightly miri test

test ctl_type_from_16_is_invalid_off_freebsd ... error: Undefined Behavior: constructing invalid value of type sysctl::CtlType: at .<enum-tag>, encountered 0x00000010, but expected a valid enum tag
  --> sysctl-0.7.1/src/ctl_type.rs:44:18
   |
44 |         unsafe { std::mem::transmute(t) }
   |                  ^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here

Fix would be to put the bound behind the same cfg as the variant, so it is t <= 16 on FreeBSD and t <= 15 elsewhere. Better still, match on the value and return CtlType::None or an error for anything unknown, which drops the transmute entirely.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions