Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

CPrimitiveType (a repr(u8) enum) is received directly by value across the C ABI with no validation

未关闭
#196 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
3/5
预计耗时
1-2 天
新手友好度
68/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
c, rust

调研方向

检查 ffi/src/lib.rs:38-45,249 中的 wirefilter_create_primitive_type 和 CPrimitiveType,然后将它们与第 94 行的 From 到 Type 的转换进行比较。在 ffi/tests/ctests 中使用有效和超出范围的原始字节运行真实的 C 覆盖测试。完成标准是:无效的 C 输入在构造 enum 之前经过验证,并且受影响的入口点能够处理无效值,而不会出现所报告的未经检查的失败。

由索引模型根据 Issue 内容生成。

描述

wirefilter_create_primitive_type(ty: CPrimitiveType) -> CType (ffi/src/lib.rs:249) takes the
#[repr(u8)] enum CPrimitiveType (valid discriminants 1..=4, ffi/src/lib.rs:38-45) directly by
value across the extern "C" boundary. The generated header exposes the C parameter as a bare
typedef uint8_t wirefilter_primitive_type; in plain-C mode — nothing on the C side restricts it to
1..=4. Constructing an out-of-range enum value this way violates Rust's own enum validity invariant
— Undefined Behavior per the language specification, independent of what any particular compiler
happens to do with it today.

A related, separately-reachable gap: impl From<CType> for Type (ffi/src/lib.rs:94) does
CPrimitiveType::try_from(cty.primitive).unwrap() — a checked conversion, but on a plain
pub primitive: u8 struct field with no C-side range enforcement. A zero-initialized
wirefilter_type_t ty = {0}; (the natural C idiom) has primitive == 0 and hits this .unwrap().
Reachable via 4 entry points that never go through wirefilter_create_primitive_type at all.

What was actually observed, dynamically, from real C callers (compiled C test via this repo's own
ffi/tests/ctests harness, both debug and release):

  • Construction does not crash on this target, in either profile. A real C call
    wirefilter_create_primitive_type((wirefilter_primitive_type)5) returns normally with
    primitive == 5 intact.
  • Using the resulting value subsequently hits the checked panic above: passing it into
    wirefilter_add_type_field_to_scheme reaches CPrimitiveType::try_from(5) → Err → .unwrap()
    panics, SIGABRT, in both debug and release, from the real C caller:
calling wirefilter_create_primitive_type((wirefilter_primitive_type)5) from real C ...
Survived call (unexpected), primitive byte = 5
calling wirefilter_add_type_field_to_scheme with the invalid-discriminant type ...

thread '...' panicked at ffi/src/lib.rs:94:67:
called `Result::unwrap()` on an `Err` value: TryFromPrimitiveError { number: 5 }
...
thread caused non-unwinding panic. aborting.
(signal: 6, SIGABRT: process abort signal)

This does not mean the raw-reception gap is "safe" in general — it means that on this specific
compiler and code path, the invalid value isn't consumed by anything that miscompiles around its
invalidity before reaching a checked conversion. Undefined Behavior isn't something a finite number of
test runs can rule out for every compiler version or future refactor that adds a match on
CPrimitiveType without going through TryFromPrimitive.

Reachability: any C caller or dynamic-binding layer invoking wirefilter_create_primitive_type
with an out-of-range byte, or constructing a raw wirefilter_type_t and passing it to any of the 4
consuming functions. Network/attacker reachability through any specific embedding is not established
here.

Suggested fix: change wirefilter_create_primitive_type's parameter to a raw u8 and validate it
with TryFromPrimitive, exactly as the From<CType> for Type path already does — this closes the
raw-ABI-reception gap and makes both paths consistent, removing the language-level UB regardless of
whether any currently-observed compiler exploits it. The remaining gap on the already-checked path is
just the missing catch_panic wrapper on its four call sites (same four as in the CompoundType depth
report).

Found with the rust-in-peace pipeline.

主要语言
Rust
星标
1.2k
派生
126
平均合并
12 小时 12 分钟
30 天内合并 PR
4

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

cloudflare/wirefilter 的其他 Issue

查看 cloudflare/wirefilter 的全部 Issue

相似的 Issue

更多 Rust Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。