Skip to main content

MAX_VALUE_NODES

Constant MAX_VALUE_NODES 

Source
const MAX_VALUE_NODES: usize = _; // 4_194_304usize
Expand description

Sanity cap on the number of Value nodes one top-level decode may materialize across every array and map in the datum. Arrays and maps apply it per block (a fast reject for an absurd single-block count) and against the shared cumulative budget threaded through the whole decode (see charge_value_nodes / DECODE_NODES).

This bounds memory, not element count: each element is weighted by min_value_nodes, a lower bound on the Value nodes it decodes into. An element-count cap alone is not enough, because a zero-width element — null, or a record of only null/empty-record fields — occupies no input yet still allocates a Value (a Vec slot, plus a record’s own Vec and field-name Strings). The min_encoded_len byte-floor check below bounds a block by the remaining input only when each element occupies at least one wire byte, so a multi-million-element block of zero-width elements would otherwise amplify a handful of bytes into gigabytes. Weighting the count and capping the product bounds that amplification (as well as the analogous case of a huge block of wide, positive-floor records read from a large input).

The budget is shared across the whole datum rather than reset per collection so the bound composes through nesting: a per-collection budget would hand every array/map a fresh ceiling, letting a schema like array<record{array<record{null}>}> amplify a few wire bytes into roughly this cap raised to the nesting depth. Sharing one budget keeps the worst case flat regardless of nesting.

Without any cap, a malicious or corrupt file can claim up to i64::MAX items and the generic array/map decode loop runs until it OOMs or hits Vec capacity-overflow.

At 1 << 22 nodes the worst case (decoding zero-width records right up to the cap) peaks around 750 MiB — including the transient doubling of the element Vec mid-push — leaving comfortable headroom under the fuzzer’s 2 GiB RSS limit, while still admitting any realistically-sized array/map.