/** * Pass #31: unbounded-collection (CWE-770, category: performance) * * Detects collections that grow unboundedly inside a loop with no * corresponding size limit check or clear/remove operation. * * Detection strategy: * 1. For each loop body (via `graph.loopBodies()`), find all calls in the * range whose method_name is a known "grow" operation. * 2. For each grow call, extract the receiver as the collection variable. * 3. Check if the loop body also contains any shrink operation (`clear`, * `remove`, `delete`, `shift`, `pop`, `removeFirst`, `poll`) on the * same receiver, OR a size-limit guard in the source text * (`size() <`, `length <`, `size() <=`, etc.). * 4. If grow-only with no limit found: emit a finding. * * Languages: Java, JavaScript/TypeScript, Python, Rust. Bash — skipped. */ import type { AnalysisPass, PassContext } from '../../graph/analysis-pass.js'; /** * Per-pass options for UnboundedCollectionPass. * Pass via `AnalyzerOptions.passOptions.unboundedCollection`. */ export interface UnboundedCollectionOptions { /** * Variable names to skip (not flag as unbounded). * Useful for known-safe collections or intentional accumulation. */ skipPatterns?: string[]; } export interface UnboundedCollectionResult { unboundedCollections: Array<{ receiver: string; line: number; loopStart: number; loopEnd: number; }>; } export declare class UnboundedCollectionPass implements AnalysisPass { readonly name = "unbounded-collection"; readonly category: "performance"; private readonly skipPatterns; constructor(options?: UnboundedCollectionOptions); run(ctx: PassContext): UnboundedCollectionResult; } //# sourceMappingURL=unbounded-collection-pass.d.ts.map