在 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 不安全
需要更多关注unsafe
代码,依赖于
第三方 crate 很可能会被拒绝,unsafe
依赖于
第三方类型的内部表示详情绝不
接受。
最后是包含 unsafe
类型的 struct
定义,例如 *const
。
*mut
或 UnsafeCell
必须包含一个说明内部
类型的不变量。如果使用 unsafe
类型执行
或者,如果它与另一类型中的内存别名,则应该有
解释它如何支持 Rust 的“别名 XOR 变更”要求。
如果出于安全原因故意省略了任何 derive
的 trait,
注释,以防止以后的编辑者添加不安全的 impl。
上述规则适用于添加的任何 unsafe
代码或任何
对现有 unsafe
代码的修改。
如需详细了解如何封装 unsafe
不变量,请参阅
Ralf Jung 的《The Scope of Unsafe》和
Niko Matsakis 的《Tootsie Pop》模型。
不安全评价
如需请求对 Rust 代码进行不安全的审核,请执行以下操作:
- 在
Language Platforms > Rust > Unsafe
组件下提交 bug。包含 在错误说明中提供指向您的评价的链接。 - 添加“Fuchsia Rust Unsafe Reviews fuchsia-rust-unsafe-reviews@google.com” 审核人员系统将随机选择一位评价者并为其分配 您的 CL。
如果您的审核具有时效性,请提高错误的优先级并留下 说明您遇到的情况