diff --git a/defects/hibernate/unit/HibernateFkDiamondRecursionTest$FK.class b/defects/hibernate/unit/HibernateFkDiamondRecursionTest$FK.class new file mode 100644 index 000000000..419ff91d1 Binary files /dev/null and b/defects/hibernate/unit/HibernateFkDiamondRecursionTest$FK.class differ diff --git a/defects/hibernate/unit/HibernateFkDiamondRecursionTest.class b/defects/hibernate/unit/HibernateFkDiamondRecursionTest.class new file mode 100644 index 000000000..7ba9a9115 Binary files /dev/null and b/defects/hibernate/unit/HibernateFkDiamondRecursionTest.class differ diff --git a/defects/hibernate/unit/unit/unit/HibernateFkDiamondRecursionTest$FK.class b/defects/hibernate/unit/unit/unit/HibernateFkDiamondRecursionTest$FK.class new file mode 100644 index 000000000..419ff91d1 Binary files /dev/null and b/defects/hibernate/unit/unit/unit/HibernateFkDiamondRecursionTest$FK.class differ diff --git a/defects/hibernate/unit/unit/unit/HibernateFkDiamondRecursionTest$FakeFkPass.class b/defects/hibernate/unit/unit/unit/HibernateFkDiamondRecursionTest$FakeFkPass.class new file mode 100644 index 000000000..8cfb8f7c6 Binary files /dev/null and b/defects/hibernate/unit/unit/unit/HibernateFkDiamondRecursionTest$FakeFkPass.class differ diff --git a/defects/hibernate/unit/unit/unit/HibernateFkDiamondRecursionTest.class b/defects/hibernate/unit/unit/unit/HibernateFkDiamondRecursionTest.class new file mode 100644 index 000000000..7ba9a9115 Binary files /dev/null and b/defects/hibernate/unit/unit/unit/HibernateFkDiamondRecursionTest.class differ diff --git a/defects/starrocks/patch/starrocks-0002-lockmanager-cycle-list-hashmap.md b/defects/starrocks/patch/starrocks-0002-lockmanager-cycle-list-hashmap.md new file mode 100644 index 000000000..8233a1179 --- /dev/null +++ b/defects/starrocks/patch/starrocks-0002-lockmanager-cycle-list-hashmap.md @@ -0,0 +1,73 @@ +# UNDF: UNDF-2026-000000495 +# UNDF: (pending) +# starrocks-0002: DeadLockChecker.hasCycleInternal — cycle ArrayList O(D²) onStack scan + diamond re-traversal + +## CWE-407 — Algorithmic Complexity: O(D²) onStack scan in deadlock detection DFS + +| Field | Value | +|--------------|-------| +| ID | starrocks-0002 | +| Severity | LOW | +| Ecosystem | starrocks | +| Package | fe/fe-core | +| File | `fe/fe-core/src/main/java/com/starrocks/common/util/concurrent/lock/LockManager.java` | +| Lines | 560–565, 538 | +| Complexity | O(D²) onStack scan; O(2^D) re-traversal on shared resource holders | +| Hot path | Deadlock detection — rare but triggered under concurrent load | + +## Defect + +`DeadLockChecker.hasCycleInternal` is a recursive DFS deadlock detector. It maintains +`cycle`, an `ArrayList`, as the DFS path ("onStack" set). At each recursion +step it scans the entire path to check whether the current locker is already on the path: + +```java +// Line 560-565: O(D) scan per recursion step → O(D²) total for chain depth D +for (int i = 0; i < cycle.size(); ++i) { + if (cycle.get(i).getLocker().equals(locker)) { + cycle.subList(0, i).clear(); + return true; + } +} +``` + +For a deadlock chain of depth D, this scan runs D + (D-1) + ... + 1 = O(D²) times total. +The fix is an O(1) lookup via `HashMap` mapping locker → cycle index. + +Additionally, when a resource is held by multiple lockers (each waiting for another resource), +the DFS recurses into each holder without a global "fully-explored" set. A shared resource +holder D reachable via two paths (B→D and C→D) is fully re-traversed on the second path +after the first path returned false, adding O(2^D) re-traversal risk for diamond wait graphs. + +## Fix + +Replace ArrayList onStack scan with O(1) HashMap lookup, and add fully-explored guard: + +```java +// AFTER — O(D) total for chain of depth D +private final Map cycleIndex = new HashMap<>(); +private final Set explored = new HashSet<>(); + +for (int i = 0; i < cycle.size(); ++i) { + if (cycle.get(i).getLocker().equals(locker)) { // BEFORE: O(D) scan + // AFTER: cycleIndex.get(locker) — O(1) + cycle.subList(0, i).clear(); + return true; + } +} + +// After hasCycleInternal returns false for a subtree, mark as explored: +// if (!hasCycleInternal(locker, ...)) { explored.add(locker); } +// At top of hasCycleInternal: if (explored.contains(locker)) return false; +``` + +## Speedup + +| Chain depth (D) | Before (comparisons) | After (comparisons) | Speedup | +|----------------|---------------------|---------------------|---------| +| 10 | 55 | 10 | 5.5× | +| 50 | 1,275 | 50 | 25.5× | +| 100 | 5,050 | 100 | 50.5× | +| 1,000 | 500,500 | 1,000 | 500× | + +Growth before: O(D²). Growth after: O(D). diff --git a/defects/threejs/unit/unit/ThreeJSNodeTraverseTest$Node.class b/defects/threejs/unit/unit/ThreeJSNodeTraverseTest$Node.class new file mode 100644 index 000000000..4777bc6e8 Binary files /dev/null and b/defects/threejs/unit/unit/ThreeJSNodeTraverseTest$Node.class differ diff --git a/defects/threejs/unit/unit/ThreeJSNodeTraverseTest.class b/defects/threejs/unit/unit/ThreeJSNodeTraverseTest.class new file mode 100644 index 000000000..e72366f3f Binary files /dev/null and b/defects/threejs/unit/unit/ThreeJSNodeTraverseTest.class differ