Rust 中的代码不安全

在 Rust 中,unsafe 是危险但有时必需的应急路径。在编写或查看 unsafe 代码时,请务必:

  • 明确确定每个 unsafe 块所需的所有假设和不变性;
  • 确保满足这些假设
  • 确保继续满足这些假设。

为了确保 unsafe 的不变量不会被未来的编辑器破坏,每次使用 unsafe 时都必须附带清晰简洁的注释,解释所做的假设。

尽可能将不安全因素打包到单个函数或模块中,以便对外界提供安全的抽象概念。FFI 调用通常应通过安全函数公开,该函数的唯一用途就是为相关函数提供一个安全封装容器。这些函数应包含包含以下信息的注释(如果适用):

  • 前提条件(例如,参数的有效状态有哪些?)
  • 失败处理(例如,应该释放哪些值?已忘记?已失效?)
  • 成功处理(例如,创建或使用了哪些值?)

示例:

impl Channel {
    /// Write a message to a channel. Wraps the
    /// [zx_channel_write](//docs/zircon/syscalls/channel_write.md)
    /// syscall.
    pub fn write(&self, bytes: &[u8], handles: &mut Vec<Handle>)
            -> Result<(), Status>
    {
        let opts = 0;
        let n_bytes = try!(usize_into_u32(bytes.len()).map_err(|_| Status::OUT_OF_RANGE));
        let n_handles = try!(usize_into_u32(handles.len()).map_err(|_| Status::OUT_OF_RANGE));

        // Requires that `self` contains a currently valid handle or ZX_HANDLE_INVALID.
        // On success, all of the handles in the handles array have been moved.
        // They must be forgotten and not dropped.
        // On error, all handles are still owned by the current process and can be dropped.
        unsafe {
            let status = sys::zx_channel_write(self.raw_handle(), opts, bytes.as_ptr(), n_bytes,
                handles.as_ptr() as *const sys::zx_handle_t, n_handles);
            ok(status)?;
            // Handles were successfully transferred, forget them on sender side
            handles.set_len(0);
            Ok(())
        }
    }
}

如果 unsafe 代码依赖于其他安全代码来确保正确性,则必须在相应的安全代码旁边添加注释,说明它必须支持的不变体和原因。依赖于多个函数行为的不变量会引起额外的审查,跨模块或跨 crate 不安全需要更加关注。依赖于第三方 crate 的正确行为的 unsafe 代码可能会被拒绝,而依赖于第三方类型的内部表示详情的 unsafe 代码将永远不会被接受。

最后,包含 unsafe 类型(如 *const*mutUnsafeCell)的 struct 定义必须包含一条注释,解释该类型的内部表示法不变体。如果使用 unsafe 类型执行突变,或者使用另一种类型的内存实现别名,则应说明它如何支持 Rust 的“别名 XOR 变更”要求。 如果出于安全原因故意省略了任何 derive 可特征,则必须添加注释,以防止未来的编辑者添加不安全的 impl。

上述规则适用于 unsafe 代码的任何添加或对现有 unsafe 代码的任何修改。

如需详细了解如何封装 unsafe 不变量,请参阅 Ralf Jung 的“不安全范围”Niko Matsakis 的“Tootsie Pop”模型

不安全的评价

如需请求对 Rust 代码进行不安全的审核,请执行以下操作:

  1. Rust>Unsafe 组件下提交 bug。在 bug 说明中添加指向您的评价的链接。
  2. 将“Fuchsia Rust Unsafe Reviews fuchsia-rust-unsafe-reviews@google.com”添加为 CL 的审核者。系统会随机选择审核人员,并将其分配给您的 CL。

如果您的审核具有时效性,请提高 bug 的优先级,并发表评论来说明您的情况。