Unsafe Rust 随堂小测(一)

论坛 期权论坛 期权     
我问   2022-6-26 02:24   8670   10
本卷总分为 100 分,时间 30 分钟。
开卷考试,资料仅限 Rust 标准库文档,禁止访问外部网站。
本卷不附带标准答案,完成后请自行订正。
第 1 题

以下 bytes_of 函数为什么是不健全(unsound)的?(30分)
/// !!!unsound!!!
pub fn bytes_of<T>(val: &T) -> &[u8] {
    let len: usize = core::mem::size_of::<T>();
    let data: *const u8 = <*const T>::cast(val);
    unsafe { core::slice::from_raw_parts(data, len) }
}
第 2 题

以下 Memory trait 的 as_bytes 方法为什么是不健全的?(30分)
2022-06-24 修改:原题面赋分过大,增加了对修复方案的要求。
以下 Memory trait 的 as_bytes 方法为什么是不健全的?(10分)
请提出至少两种修复方案,使该 trait 健全。(20分)
pub trait Memory {
    fn addr(&self) -> *const u8;

    fn length(&self) -> usize;

    /// !!!unsound!!!
    fn as_bytes(&self) -> &[u8] {
        let data: *const u8 = self.addr();
        let len: usize = self.length();
        unsafe { core::slice::from_raw_parts(data, len) }
    }
}
第 3 题

以下 alloc_for 函数为什么是不健全的?(10分)
请写出修复方案,不能改变函数签名。(10分)
/// !!!unsound!!!
pub fn alloc_for<T>() -> *mut u8 {
    let layout = std::alloc::Layout::new::<T>();
    unsafe { std::alloc::alloc(layout) }
}
第 4 题

以下 read_to_vec 函数为什么是不健全的?(10分)。
请写出修复方案,不能改变函数签名。(10分)
use std::io;

/// !!!unsound!!!
pub fn read_to_vec<R>(mut reader: R, expected: usize) -> io::Result<Vec<u8>>
where
    R: io::Read,
{
    let mut buf: Vec<u8> = Vec::new();
    buf.reserve_exact(expected);
    unsafe { buf.set_len(expected) };
    reader.read_exact(&mut buf)?;
    Ok(buf)
}
分享到 :
0 人收藏

10 个回复

倒序浏览
2#
3tuol  1级新秀 | 2022-6-26 02:25:18
T1:内部可变性T2:不正确的addr和length会破坏内存安全T3:zst,特判T4:可能是u8未初始化,文档里的例子先赋值后set_len…不过如果是这样感觉也太苛刻了…
3#
y4jh8  1级新秀 | 2022-6-26 02:25:37
rfc2930,的确是unsound
4#
nmq6pm  1级新秀 | 2022-6-26 02:26:10
T1还有其他问题
5#
37rbx  1级新秀 | 2022-6-26 02:26:49
uninit?
6#
吴宇  管理员  伦敦金丝雀码头交易员 | 2022-6-26 02:27:15
T1 padding bytes是否是未定义的?我也不确定,只是提一个想法。
7#
13607123105  1级新秀 | 2022-6-26 02:28:01
内存不可字节寻址?
8#
b9rt  1级新秀 | 2022-6-26 02:28:44
https://docs.rs/bytemuck/latest/bytemuck/fn.bytes_of.html
9#
wdhzmj  1级新秀 | 2022-6-26 02:29:10
T4 是 UB,任何未初始化的内存,读或者获取 reference 都是 UB,这时候只能操作指针
10#
hqzu7_  1级新秀 | 2022-6-26 02:30:09
1. T的layout可能包含未初始化的u8, 比如padding
2. addr() 和 length() 可能返回无效的值, unsafe 代码不能依赖 safe 代码的正确实现
3. T可能是ZST. 修复的话,取决于具体要求可以在遇到到ZST时 panic, 返回 null, 返回 NonNull::dangling() 等等
4. read_exact 的实现有可能会读取其入参的内容, 从而访问到未初始化的内存. 其实严格来说那个 set_len 的 safety 需求就没有满足. 修复的话可以将 buf 改成 vec![0; expected], 或者使用还在 unstable 的 ReadBuf api
11#
uh9kc  1级新秀 | 2022-6-26 02:30:41
修改:T2 原题面赋分过大,增加了对修复方案的要求。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:
精华:
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP