Crates.io | isrepr |
lib.rs | isrepr |
version | 0.1.0 |
source | src |
created_at | 2023-05-07 16:40:47.697656 |
updated_at | 2023-05-07 16:40:47.697656 |
description | Generating validation from arbitrary memory to repr(C) types |
homepage | https://github.com/Samsung/rust-repr |
repository | https://github.com/Samsung/rust-repr |
max_upload_size | |
id | 859265 |
size | 37,493 |
A crate for safely converting arbitrary memory into Rust types.
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();
}