【问题标题】:Helper function to safely read structure from stream从流中安全读取结构的辅助函数
【发布时间】:2015-05-28 10:23:53
【问题描述】:

假设我们有一个单一地址空间的操作系统。为了保持稳定性,我们需要对用户应用程序强制进行内存保护,例如禁止使用“不安全”关键字,除非用户有特殊能力。

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

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

#![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)
}

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

【问题讨论】:

    标签: rust osdev


    【解决方案1】:

    您可以使用所谓的“Marker Trait”:一个自定义的不安全 trait,所有类型的默认 impl 和所有引用的否定 trait impl。由于您禁止使用unsafe,因此用户无法自行实现该特征,因此任何具有引用的类型都无法实现该特征。

    您可能还应该在否定 impl 中包含原始指针(*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"));
    }
    

    这将无法编译:

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

    【讨论】:

    • 谢谢,正是我想要的。
    • 注意:另请阅读cglab.ca/~abeinges/blah/rust-unsafe-intro。它提到在不是#[repr(C)] 的类型之间转换会导致未定义的行为。所以你也应该检查一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    相关资源
    最近更新 更多