You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Severity: Low (process/tooling improvement, not a live bug)
Summary
Found during #1666's review (the #1634 fix). This is now the fourth independently-discovered instance of the same bug shape — an infallible Vec/String allocation sized by a product (or otherwise generator-controlled magnitude) of independently-controlled lengths, handed straight to the allocator instead of a try_reserve-style fallible guard:
Each occurrence was found independently, by a human or a multi-agent review pass noticing the pattern by eye — nothing in CI or clippy flags a raw Vec::with_capacity/String::with_capacity (or an implicit TrustedLencollect) whose argument is a multiplication of two or more independent lengths, or a scalar read from generator/document-controlled input. #1666 itself demonstrates the detection gap concretely: its first commit patched only eval.rs's copies of eval_index_expr/eval_slice_expr, and needed a second commit, prompted by a second multi-agent review pass, to catch that eval_generic.rs independently reimplements both functions (the actual CLI dispatch path) with the identical unguarded pattern.
Suggested fix direction (needs its own scoping pass)
A clippy::disallowed_methods (or similar) lint entry scoped to src/jq/ banning a bare Vec::with_capacity/String::with_capacity call would turn this into a compile-time gate instead of a review-time hope. This needs its own scoping work:
Enumerate the legitimate single-length (or length-times-constant) call sites that would need a per-call-site #[allow(...)] or a rewrite to use try_reserve_product/an equivalent single-factor helper (json/standard.rs, output.rs, yq_runner.rs, etc. all have benign with_capacity(x.len()) calls today).
Decide whether the lint should be src/jq/-wide or narrower (e.g. only eval.rs/eval_generic.rs, where the generator/cross-product pattern actually recurs).
A separate, larger structural question raised in the same review pass but explicitly out of scope for a lint-only fix: eval.rs and eval_generic.rs maintain independent, parallel reimplementations of eval_index_expr/eval_slice_expr (and likely other evaluator logic) with no mechanism keeping them in sync — this is the root cause #1666 needed a second commit to fully close. Whether to consolidate these two evaluators (or add some other cross-checking mechanism) is a much bigger question than this issue's own scope; noted here for visibility, not as this issue's own acceptance criterion.
Severity: Low (process/tooling improvement, not a live bug)
Summary
Found during #1666's review (the #1634 fix). This is now the fourth independently-discovered instance of the same bug shape — an infallible
Vec/Stringallocation sized by a product (or otherwise generator-controlled magnitude) of independently-controlled lengths, handed straight to the allocator instead of atry_reserve-style fallible guard:cannot_grow_array/pad_with_nulls(setpath's array-grow)arith_mul's string-repeat guard (s * n)eval.rs/eval_generic.rs's computed-index/-slice cross productscombinations(n)/cartesian_product(confirmed live abort)Each occurrence was found independently, by a human or a multi-agent review pass noticing the pattern by eye — nothing in CI or
clippyflags a rawVec::with_capacity/String::with_capacity(or an implicitTrustedLencollect) whose argument is a multiplication of two or more independent lengths, or a scalar read from generator/document-controlled input. #1666 itself demonstrates the detection gap concretely: its first commit patched onlyeval.rs's copies ofeval_index_expr/eval_slice_expr, and needed a second commit, prompted by a second multi-agent review pass, to catch thateval_generic.rsindependently reimplements both functions (the actual CLI dispatch path) with the identical unguarded pattern.Suggested fix direction (needs its own scoping pass)
A
clippy::disallowed_methods(or similar) lint entry scoped tosrc/jq/banning a bareVec::with_capacity/String::with_capacitycall would turn this into a compile-time gate instead of a review-time hope. This needs its own scoping work:#[allow(...)]or a rewrite to usetry_reserve_product/an equivalent single-factor helper (json/standard.rs,output.rs,yq_runner.rs, etc. all have benignwith_capacity(x.len())calls today).src/jq/-wide or narrower (e.g. onlyeval.rs/eval_generic.rs, where the generator/cross-product pattern actually recurs).try_reserve_product's hardcoded "computed-index expansion" error wording (src/jq/eval.rs) should be parameterized (a&str/enum label) before other call sites (e.g.combinations(n)per jq: combinations(n)/cartesian_product have the same unguarded allocation-product crash as #1612/#1634 #1669) start reusing it, so the error text doesn't mislead for a differently-shaped caller.A separate, larger structural question raised in the same review pass but explicitly out of scope for a lint-only fix:
eval.rsandeval_generic.rsmaintain independent, parallel reimplementations ofeval_index_expr/eval_slice_expr(and likely other evaluator logic) with no mechanism keeping them in sync — this is the root cause #1666 needed a second commit to fully close. Whether to consolidate these two evaluators (or add some other cross-checking mechanism) is a much bigger question than this issue's own scope; noted here for visibility, not as this issue's own acceptance criterion.Related
#1017, #1612, #1634 (closed by #1666), #1669 — the four known instances of this bug shape.