isrepr 0.1.0

Generating validation from arbitrary memory to repr(C) types
Documentation
  • Coverage
  • 92.31%
    12 out of 13 items documented3 out of 3 items with examples
  • Size
  • Source code size: 38.34 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 2.2 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 13s Average build duration of successful builds.
  • all releases: 13s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • Samsung/rust-repr
    6 1 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • Wesmania

A crate for safely converting arbitrary memory into Rust types.

Intro

Imagine you have an enum type, like so:

#[repr(C)]
enum Foo {
    FOO(u16, u32),
    BAR,
    BAZ(usize, *const ()),
}

Say that you have a pointer to that enum that came from an untrusted context, like a wonky C API or from a userspace process to your kernel:

let foo: *const Foo = todo!()

While pointer alignment is easy to verify, "untrusted context" means that the memory behind the pointer can be arbitrary. We can't simply convert the pointer to such memory to a reference, since this can lead to undefined behaviour.

Fortunately, the layout for properly defined #[repr(C)] types is well-defined. Unfortunately, working with this layout involves writing a lot of boilerplate, especially for enums.

This crate does the boilerplate for you, like so:

use isrepr::{IsRepr, Repr, ReprError};
use core::convert::TryInto;
use core::mem::transmute;

#[derive(IsRepr, Clone, Copy, Debug, PartialEq, Eq)]
enum Foo {
    FOO(u16, u32),
    BAR,
    BAZ(usize, *const ()),
}

// Repr<Foo> can have any memory contents.
fn bar(f_repr: Repr<Foo>) -> Result<Foo, ReprError> {
    f_repr.repr_try_into()
}

fn main() {
    // Pretend that we're some untrusted context.
    let foo = bar(unsafe { transmute(Foo::BAR) }).unwrap();
    assert_eq!(foo, Foo::BAR);

    // Send an invalid value!
    bar(unsafe { transmute(17u8) }).unwrap_err();
}

Links