CPrimitiveType (a repr(u8) enum) is received directly by value across the C ABI with no validation
还没有人认领这个 Issue。
评估
- 难度
- 3/5
- 预计耗时
- 1-2 天
- 新手友好度
- 68/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
调研方向
检查 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 == 5intact. - Using the resulting value subsequently hits the checked panic above: passing it into
wirefilter_add_type_field_to_schemereachesCPrimitiveType::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 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
cloudflare/wirefilter 的其他 Issue
-
AlwaysListMatcher::match_value always returns false, contradicting its own doc comment可能已有人在做 @sean0407 于 11 天前认领。 未关闭
难度 1/5 1-3 小时 新手友好度 90/100
cloudflare/wirefilter#190 ·
-
难度 4/5 3-5 天 新手友好度 45/100
cloudflare/wirefilter#208 ·
-
难度 4/5 1-2 天 新手友好度 32/100
cloudflare/wirefilter#204 · 2 条评论 ·
-
难度 4/5 3-5 天 新手友好度 68/100
cloudflare/wirefilter#195 · 1 条评论 ·
-
难度 4/5 3-5 天 新手友好度 65/100
cloudflare/wirefilter#194 ·
查看 cloudflare/wirefilter 的全部 Issue
相似的 Issue
-
bug priority: low ui
难度 2/5 1-3 小时 新手友好度 65/100
storytold/photocraft#10370 · 1 条评论 ·
维护者通常 1 天内回复
-
area:doc bug in progress needs-triage
难度 2/5 1-3 小时 新手友好度 72/100
bherbruck/solvecraft#9634 · 2 条评论 · 1 个 reaction ·
-
inflate: total_in uses plain += on c_ulong (32-bit on Windows), panics in debug for streams > 4 GiB未关闭
难度 1/5 1 小时以内 新手友好度 85/100
trifectatechfoundation/zlib-rs#570 · 1 条评论 ·
-
bug discord-triage
难度 2/5 1-3 小时 新手友好度 84/100
LanternOps/breeze#10755 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 65/100
aranya-project/aranya#803 ·