Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

CompoundType's 32-layer depth cap panics instead of rejecting, reachable from JSON deserialization and the FFI type-builder

Đang mở
#195 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

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
Công nghệ
c, rust

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:

  1. engine's own Deserialize impl for Type/CompoundType, reachable from the FFI's execution-context snapshot/restore JSON format ($lists entry's type field).
  2. ffi's CType::push (ffi/src/lib.rs:61-69) mirrors CompoundType but has no matching 32-layer guard of its own — it accumulates layer bits into a u32/u8 pair indefinitely. The panic only fires when the accumulated CType is converted back via impl From<CType> for Type (ffi/src/lib.rs:88-102), reachable via ordinary, well-formed repeated calls to wirefilter_create_array_type during 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

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của cloudflare/wirefilter

Tất cả issue của cloudflare/wirefilter

Issue tương tự

Thêm issue về Rust

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.