#parser #untrusted #simd #text-parser

no-std dangerous

安全且明确地解析不受信任/危险数据

10 个重大版本

0.10.0 2021年6月4日
0.9.0 2021年2月18日
0.8.0 2021年2月2日
0.5.0 2020年11月20日

#1246 in 解析器实现


zc 中使用

MIT 许可证

255KB
5.5K SLoC

Build Status Coverage Status Crate Docs

rust-dangerous

Rust 库,用于安全且明确地处理不受信任的(即 dangerous)数据
文档托管在 docs.rs

dangerous = "0.10"

目标

  • 快速解析。
  • 快速编译。
  • 无 panic [1]。
  • 零成本抽象。
  • 最小依赖 [2]。
  • 重试/流协议支持。
  • no-std / 适用于嵌入式。
  • 在成功路径上无堆分配 [3]。
  • 支持原始类型。
  • 可选详细错误。
  • 尽可能使用 SIMD 优化。

[1] 由于 OOM 而导致的 panic 不在范围之内。如果这令人担忧,请禁用堆分配。
[2] 当同时禁用 unicodesimd 功能时,零依赖。
[3] 当禁用 full-backtrace 功能时,无堆分配。

此库的目的是提供一个简单的接口,用于安全地显式解析不受信任的数据。dangerous 在解析二进制或简单的文本数据格式和协议方面非常出色。它不是一个像 serde 提供的序列化库,但你可以使用 dangerous 编写一个解析器,该解析器可以在反序列化程序中使用。

panic 和未处理/未确认的数据是此库试图防止的两个常见错误。包括一个可选的、但很可靠的调试接口,具有合理的输入格式和有用的错误信息,以便在生产之前或之后排除问题。

用法

fn decode_message<'i, E>(r: &mut BytesReader<'i, E>) -> Result<Message<'i>, E>
where
    E: Error<'i>,
{
    r.context("message", |r| {
        // Expect version 1
        r.context("version", |r| r.consume(0x01))?;
        // Read the body length
        let body_len = r.context("body len", |r| r.read_u8())?;
        // Take the body input
        let body = r.context("body", |r| {
            let body_input = r.take(body_len as usize)?;
            // Decode the body input as a UTF-8 str
            body_input.to_dangerous_str()
        })?;
        // We did it!
        Ok(Message { body })
    })
}

let input = dangerous::input(/* data */);
let result: Result<_, Invalid> = input.read_all(decode_message);

错误

对于协议的自定义错误通常不会提供关于为什么以及在哪里发生特定问题的上下文。传递像 core::str::Utf8Error 这样简单的错误可能足以在开发时进行调试,然而,如果只是写入日志而没有输入/上下文,通常会成为噪音。在这个阶段,你几乎更好的选择是一个简单的输入错误。

对于任何简单的递归下降解析器,这个问题会加剧,因为子切片的上下文会丢失,这使得将任何错误偏移量传递回根时无用的。通过捕获错误周围和上方的上下文,dangerous 修复了这个问题。

你曾尝试从这个类似的东西反向工作吗?

[ERRO]: ahhh!: Utf8Error { valid_up_to: 2, error_len: Some(1) }

这会更好吗?

[ERRO]: ahhh!: error reading message: error attempting to convert input into string: expected utf-8 code point
> [01 05 68 65 ff 6c 6f]
               ^^       
additional:
  error offset: 4, input length: 7
backtrace:
  1. `read all input`
  2. `<context>` (expected message)
  3. `<context>` (expected body)
  4. `convert input into string` (expected utf-8 code point)

灵感

此项目最初受到 untrusted 的启发。

依赖

~0–1MB
~16K SLoC