CompoundType's 32-layer depth cap panics instead of rejecting, reachable from JSON deserialization and the FFI type-builder
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 68/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Lĩnh vực
- backend-api-design, security
Hướng nghiên cứu
Bắt đầu trong engine/src/types.rs tại CompoundType::push và CompoundType::from_type, sau đó kiểm tra ffi/src/lib.rs tại CType::push, phần chuyển đổi CType và năm điểm vào FFI được nêu tên. Tái hiện trường hợp 34 lớp bằng harness ffi/tests/ctests và xác minh rằng việc deserialization và xây dựng kiểu lặp lại trả về lỗi mà không gây ra panic hoặc hủy tiến trình.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
CompoundType::push (engine/src/types.rs:1006-1018) enforces a hard 32-layer cap on nested
Array/Map types, returning None once self.len >= 32. Its only caller,
CompoundType::from_type (types.rs:958-970), treats that None as fatal:
// engine/src/types.rs
match match ty {
...
Type::Array(ty) => ty.push(Layer::Array),
...
} {
Some(ty) => ty,
None => panic!("Could not convert type to compound type"), // types.rs:968
}
Two producers feed this panic, neither validating depth beforehand:
engine's ownDeserializeimpl forType/CompoundType, reachable from the FFI's execution-context snapshot/restore JSON format ($listsentry'stypefield).ffi'sCType::push(ffi/src/lib.rs:61-69) mirrorsCompoundTypebut has no matching 32-layer guard of its own — it accumulates layer bits into au32/u8pair indefinitely. The panic only fires when the accumulatedCTypeis converted back viaimpl From<CType> for Type(ffi/src/lib.rs:88-102), reachable via ordinary, well-formed repeated calls towirefilter_create_array_typeduring scheme/type construction.
None of wirefilter_deserialize_json_to_execution_context, wirefilter_add_type_field_to_scheme,
wirefilter_add_always_list_to_scheme, wirefilter_add_never_list_to_scheme, or
wirefilter_serialize_type_to_json wraps this in catch_panic.
The real trigger is depth 34, not 33 — the recursive layer-accounting means the cap is hit one
level later than a naive count suggests (each layer's conversion pushes onto the previous level's
already-built CompoundType).
Confirmed crossing the real C ABI boundary, via a compiled C test program (built against this
repo's own ffi/tests/ctests harness) that constructs
{"$lists":[{"type":<34 nested Array wrappers>,"data":{}}]} and calls
wirefilter_deserialize_json_to_execution_context:
thread '...' panicked at engine/src/types.rs:968:21:
Could not convert type to compound type
thread caused non-unwinding panic. aborting.
... (signal: 6, SIGABRT: process abort signal)
This is a genuine process abort observed from the C caller's side, not an in-process Rust-only panic.
wirefilter_enable_panic_catcher() is never called in this test (defaults to disabled), consistent
with an ordinary embedding that hasn't explicitly enabled it.
Reachability: whether attacker-supplied JSON reaches the deserialization path (vs. only
host-produced serialized state) depends on the embedding. The FFI/CType path requires the ability to
construct a scheme with 34+ nested array/map layers — a schema/type-construction-time actor, not raw
per-request traffic. The wasm bindings (wasm/src/lib.rs) expose only Scheme::try_from(fields) —
scheme construction only, no JSON-ingestion API — so this doesn't apply to the wasm surface as
currently shipped.
Not memory corruption — a clean panic/abort (DoS) in both paths.
Suggested fix: add an explicit depth check (reject at deserialize time, or in CType::push, once
depth would exceed 32) that returns a normal error instead of relying on the internal cap to panic.
Give CType::push the same if self.len >= 32 { None } guard CompoundType::push already has, and
propagate that as an error rather than panicking downstream. Wrap the five consuming FFI functions in
catch_panic regardless, as defense in depth.
Found with the rust-in-peace pipeline.
- Ngôn ngữ chính
- Rust
- Star
- 1.2k
- Fork
- 126
- Merge trung bình
- 12 giờ 12 phút
- Pull request đã merge (30 ngày)
- 4
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của cloudflare/wirefilter
-
AlwaysListMatcher::match_value always returns false, contradicting its own doc commentCó thể đã có người làm @sean0407 đã nhận 11 ngày trước. Đang mở
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 90/100
cloudflare/wirefilter#190 ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
cloudflare/wirefilter#208 ·
-
Độ khó 4/5 1-2 ngày Mức phù hợp với người mới 32/100
cloudflare/wirefilter#204 · 2 bình luận ·
-
CPrimitiveType (a repr(u8) enum) is received directly by value across the C ABI with no validationĐang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
cloudflare/wirefilter#196 ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 65/100
cloudflare/wirefilter#194 ·
Tất cả issue của cloudflare/wirefilter
Issue tương tự
-
ai_p2 bug comp-datalake
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
ClickHouse/ClickHouse#128306 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
documentation
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
Maintainer thường phản hồi trong vòng 1 ngày
-
bug triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Remove the preset version numberĐang mởarea: ui enhancement good first issue
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
JavenKazebee/capture-room#166 ·
Maintainer thường phản hồi trong vòng 1 ngày