Helper功能可以安全地从流中读取结构

aba*_*abo 3 osdev rust

假设我们有一个单地址空间的操作系统.为了保持稳定性,我们需要强制用户应用程序的内存保护,例如禁止使用'unsafe'关键字,除非用户具有特殊功能.

我们的用户需要有一种方法可以安全地从/向字节流(例如文件)读/写任意结构.当然,我们谈论的是不包含引用的结构(否则我们会失去内存安全性).

现在我尝试实现这种通用的阅读器功能:

#![feature(core)]

use std::io;
use std::mem;
use std::raw;

fn read<T>(reader: &mut io::Read, dest: &mut T) -> io::Result<usize> {
    let slice = raw::Slice{ data:dest, len:mem::size_of::<T>() };
    let buf: &mut [u8] = unsafe { mem::transmute(slice) };
    reader.read(buf)
}
Run Code Online (Sandbox Code Playgroud)

上面的实现有一个严重的问题.它允许读取包含引用的结构.那我怎么解决这个问题呢?

oli*_*obk 5

您可以使用所谓的"标记特征":一种自定义的不安全特征,其中包含所有类型的默认impl和所有引用的负特征impl.由于您禁止所有使用unsafe,因此用户无法自行实现特征,因此对于任何具有引用的类型都不能实现特征.

您可能还应该在负数impls中包含原始指针(*mut*const)...否则用户可能会反序列化一个Vec或其他一些内部不安全的"安全"类型.

#![feature(optin_builtin_traits)]

unsafe trait NoInnerRefs {}

impl<'a, T> !NoInnerRefs for &'a T {}
unsafe impl NoInnerRefs for .. {}

struct A(&'static str);

struct B(i32);

fn test<T: NoInnerRefs>(_: T) {
}

fn main() {
    test(B(5));
    test(A("hi"));
}
Run Code Online (Sandbox Code Playgroud)

这将无法编译:

<anon>:17:5: 17:9 error: the trait `NoInnerRefs` is not implemented for the type `&'static str` [E0277]
<anon>:17     test(A("hi"));
              ^~~~
Run Code Online (Sandbox Code Playgroud)

  • 注意:另请阅读http://cglab.ca/~abeinges/blah/rust-unsafe-intro/.它提到在不是"#[repr(C)]"的类型之间进行转换会导致未定义的行为.所以你也应该检查一下. (2认同)