java-topology/defects/lucene/patch/lucene-CLEAN.md
russell@unturf.com a629bd0bbf no-stone-unturned wave: 8 new defects, 15 CLEAN confirmations; count 621→629
New defects (all PASS):
- exim-0001: same_hosts() MX-segment O(H²) → AVL set O(H log H), 10.5x at H=20
- minecraft-0001: DependencySorter.isCyclic no visited set O(E^D) → O(E), 342,000x at D=24
- minecraft-0002: PistonStructureResolver toPush ArrayList O(N²) → HashSet O(N)
- minecraft-0003: RedstoneWireEvaluator Deque.contains O(N²) → HashSet O(N)
- minecraft-0004: MoveThroughVillageGoal visited List O(N²) → HashSet O(N)
- mpich-0001: group_lpid_to_rank O(N²) → HashMap O(N), 313x at N=1000
- ompi-0001: group_overlap process-name scan O(N×M) → HashMap O(N+M), 2048x
- pcl-0001: RegionGrowing::getSegmentFromPoint O(C×S) → point_labels[] O(1), 50000x

CLEAN confirmed: esbuild, express, koa, ktor, lucene, mpich-recvq, ompi-startup,
  prosody, roda, rust/rustc-wave2, signal-server, solana, wiredtiger, wireguard-tools,
  linux-kernel (pointer to linux/)
2026-03-29 16:11:50 -04:00

3.3 KiB
Raw Blame History

Lucene CWE-407 Scan — CLEAN

Date: 2026-03-29 Target: Apache Lucene (~/git/lucene/) Language: Java Version: main branch (depth-1 clone)

Scan Scope

Area Files Checked
lucene/core/src/java/org/apache/lucene/index/ IndexWriter, TieredMergePolicy, LogMergePolicy, TemporalMergePolicy, SegmentInfos, ReaderPool, DocumentsWriterPerThreadPool, BufferedUpdatesStream, UpgradeIndexMergePolicy, ConcurrentMergeScheduler, PerFieldMergeState
lucene/core/src/java/org/apache/lucene/search/ BooleanQuery
lucene/core/src/java/org/apache/lucene/util/hnsw/ UpdateGraphsUtils
lucene/core/src/java/org/apache/lucene/codecs/perfield/ PerFieldMergeState

Methodology

Searched for List.contains(), ArrayList.contains(), Collection.contains(), and .indexOf() calls nested inside loops over segment lists or merge candidates. Cross-referenced the declared type of each collection receiving a .contains() call.

Findings

All .contains() calls in hot paths use hash-backed collections:

Location Collection Type Verdict
TieredMergePolicy.java:316,765,938 merging Set<SegmentCommitInfo> (from getMergingSegments()) O(1)
LogMergePolicy.java:497 mergingSegments Set<SegmentCommitInfo> O(1)
TemporalMergePolicy.java merging Set<SegmentCommitInfo> O(1)
IndexWriter.java:2268 pendingMerges ArrayDeque<OneMerge> — but call is not in inner loop, just poll loop once O(D) one-shot
IndexWriter.java:2268 runningMerges HashSet<OneMerge> O(1)
IndexWriter.java:3862 mergedSegmentNames HashSet<String> (constructed on line 3862) O(1)
IndexWriter.java:6445 alreadySeenSegments Set<SegmentCommitInfo> (parameter type) O(1)
IndexWriter.java:5482 mergeExceptions ArrayList<OneMerge> — called once in addMergeException(), not in a segment loop O(E) isolated
BooleanQuery.java:404,412 intersection HashSet<Query> O(1)
BooleanQuery.java:367368 clause sets Collection<Query> backed by map values (List per Occur) rewrite-time, bounded clauses
PerFieldMergeState.java:105,108 filteredNames HashSet<String> O(1)
UpdateGraphsUtils.java:45,74 j IntHashSet O(1)

Notable Non-Defects

  • IndexWriter.java:5482 mergeExceptions.contains(merge): mergeExceptions is an ArrayList, but addMergeException() is only called when a merge throws an exception (error path, infrequent). It is not called inside a per-segment loop. Not a hot path.

  • IndexWriter.java:2268 pendingMerges.contains(merge): pendingMerges is an ArrayDeque (O(N) contains), and this is called inside a loop over spec.merges (up to N merges, each checked). This is waitForMerges() — only called when the caller explicitly waits for forced merges to complete. Not a per-document or per-query hot path. Excluded.

Result

CLEAN — no CWE-407 defects confirmed in Lucene core.

The codebase consistently uses Set<> or HashSet<> for merge-state membership checks in the hot segment-iteration paths. The design is intentionally correct: getMergingSegments() returns a Set<SegmentCommitInfo> specifically so that callers can do O(1) membership checks in their segment-iteration loops.