Fix H1: bound untrusted array counts; resolve L1 (review #006)
- Replace the three Vec::with_capacity(count) sites in materialize.rs with Vec::new() — validate_bytes on an adversarial count no longer OOM-aborts the process (AGENTS.md §3). - New compile-time caps in schema.rs: MAX_ARRAY_ELEMENTS (2^16, enforced at BastArray::parse — the choke point every consumer inherits, bounds the walkers' per-element entry loops) and MAX_ARRAY_BYTES (2^26, enforced per walker against the mode-specific stride: compile_array, walk_array, compute_array_field). - L1: fixed_composite_size/fixed_plan_size now return Result<Option<usize>>; unwrap_or_default() gone, overflow is a clean Schema error instead of silent stride-0. - Zero-progress guard: stride-0 arrays whose elements consume 0 bytes (legal empty-struct elements) now error in plan_walk_variable_array_ size and materialize_array_packed instead of looping count times. - Tests: 8 new (parse/build/compile rejections, cap boundary, short-buffer clean error) + array_count_large_u64_parses_on_64bit rewritten to assert the new cap rejection. In-tree tests assert only the safe (compile-time) half per review #006's Methodology warning. - Review #006 updated: H1/L1 resolution blocks, new finding N2 (unbounded align annotations, found while re-deriving the cap arithmetic), resolution log, recommended order. Verified: 482 tests green (405+17+34+14+12, 2 pre-existing ignored), clippy -D warnings clean, wasm32-unknown-unknown build green.
This commit is contained in:
1 parent
27be01af93
commit
2d166f567b
8 files changed
+453
-49
No files matched your search
@@ -16,6 +16,20 @@ use std::fmt;
|
||||
pub(crate) const U32_SIZE: usize = 4;
|
||||
pub(crate) const DISCRIMINATOR_PATH: &str = "__discriminator";
|
||||
|
||||
/// Maximum declared array element count. Schemas are untrusted input
|
||||
/// (AGENTS.md §3): every layout walker expands `count` into per-element
|
||||
/// work (offset-map/layout entries, per-element reads), so an unbounded
|
||||
/// count is a memory/CPU denial-of-service. The cap applies at parse
|
||||
/// time, before any walker sees the array; 2^16 elements bounds the
|
||||
/// per-array compile-time entry cost at ~10 MB.
|
||||
pub(crate) const MAX_ARRAY_ELEMENTS: usize = 1 << 16;
|
||||
|
||||
/// Maximum computed byte size of a single array (`count × element
|
||||
/// stride`). Bounds the arithmetic product independently of
|
||||
/// [`MAX_ARRAY_ELEMENTS`] so multi-megabyte strides cannot combine with
|
||||
/// a legal count into an unbounded layout request.
|
||||
pub(crate) const MAX_ARRAY_BYTES: usize = 1 << 26;
|
||||
|
||||
/// The 18 BAST kinds recognized by the engine.
|
||||
///
|
||||
/// Each variant corresponds to a lowercase BAST kind string
|
||||
|
||||
Reference in new issue
Block a user