22个重大版本更新
0.44.1 | 2024年8月13日 |
---|---|
0.43.0 | 2024年7月23日 |
0.34.0 | 2024年3月13日 |
0.32.0 | 2023年12月8日 |
0.1.0 | 2022年2月17日 |
1490 在 编码 中排名
每月下载量 6,487
用于 29 个crate (9 直接使用)
80KB
2K SLoC
quic-codec
用于以安全和性能为导向的方式解码和编码值的工具。
这是一个由 s2n-quic 使用的内部crate。API目前不稳定,不应直接使用。
解码器
考虑以下代码
fn decode_u8(buffer: &[u8]) -> (u8, &[u8]) {
let value = buffer[0];
(value, buffer[1..])
}
decode_u8(&[1, 2, 3]); // => (1, &[2, 3])
decode_u8(&[4]); // => (4, &[])
尽管在Rust中这是安全的,但在缺少输入的情况下这种方法会panic
decode_u8(&[]) // thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0'
这类问题难以检测,可能会对服务器等环境中传入的不受信任数据造成重大影响。攻击者可能构建一个会使服务器崩溃的有效负载。
缓解这些问题的可能方法之一是进行检查
fn decode_u8(buffer: &[u8]) -> Result<(u8, &[u8]), Error> {
if buffer.len() < 1 {
return Err(Error::OutOfBounds);
}
let value = buffer[0];
Ok((value, buffer[1..]))
}
decode_u8(&[1, 2, 3]); // => Ok((1, &[2, 3]))
decode_u8(&[4]); // => Ok((4, &[]))
decode_u8(&[]); // => Err(Error::OutOfBounds)
这种解决方案适用于特定情况,但容易出错,因为它要求对每个切片访问都断言其预置条件集。特别是当解码值的长度依赖于之前解码的不受信任的输入时,需要特别小心。
fn decode_slice(buffer: &[u8]) -> Result<(&[u8], &[u8]), Error> {
if buffer.len() < 1 {
return Err(Error::OutOfBounds);
}
let len = buffer[0] as usize;
if buffer.len() < len {
return Err(Error::OutOfBounds);
}
let value = buffer[1..len];
Ok((value, buffer[len..]))
}
quic-codec
提供了一个保证不会panic的切片接口。它是通过强制执行检查并处理预置条件违反来实现的。
fn decode_u8(buffer: DecoderBuffer) -> DecoderResult<u8> {
let (value, buffer) = buffer.decode::<u8>()?;
Ok((value, buffer))
}
通过类型推断解码获得另一个主要优势。DecoderBuffer::decode
函数可以扩展以支持任何类型,前提是它实现了 DecoderValue
特性。考虑以下示例,其中使用相同的 decode
函数调用解析 u32
,u8
和 Date
本身
struct Date {
year: u32,
month: u8,
day: u8,
}
impl<'a> DecoderValue<'a> for Date {
fn decode(buffer: DecoderBuffer<'a>) -> DecoderResult<'a, Self> {
let (year, buffer) = buffer.decode()?;
let (month, buffer) = buffer.decode()?;
let (day, buffer) = buffer.decode()?;
let date = Self { year, month, day };
Ok((date, buffer))
}
}
fn decode_two_dates(buffer: DecoderBuffer) -> DecoderResult<(Date, Date)> {
let (first, buffer) = buffer.decode()?;
let (second, buffer) = buffer.decode()?;
Ok(((first, second), buffer))
}
编码器
EncoderBuffer 是 DecoderBuffer 的对应物。它将实现 EncoderValue
的任何值写入预先分配的可变切片。每种类型都提供关于最终编码大小的提示,以确保在编码值时只进行一次分配。
依赖关系
~1–2MB
~36K SLoC