#repr #memory #enums #safely #converting #type #isrepr

isrepr_macros

为 'isrepr' crate 提供过程宏的crate

1个不稳定版本

0.1.0 2023年5月7日

#38#repr


用于 isrepr

MIT 许可证

40KB
1K SLoC

一个将任意内存安全转换为Rust类型的crate。

简介

想象你有一个枚举类型,如下所示

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

比如说,你有一个指向该枚举的指针,它来自一个不可信的上下文,比如一个古怪的C API或者来自用户空间进程到你的内核

let foo: *const Foo = todo!()

虽然指针对齐很容易验证,但“不可信的上下文”意味着指针后面的内存可以是任意的。我们不能简单地将这样的内存转换为引用,因为 这样会导致未定义行为

幸运的是,正确定义的 #[repr)] 类型的布局是 明确定义的。不幸的是,处理这种布局需要编写大量的模板代码,尤其是对于枚举。

这个crate为你处理模板代码,如下所示

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

#[derive(IsRepr, Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
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();
}

链接

依赖项

~1.5MB
~35K SLoC