cleanup: remove duplicate hibernate-0007/quarkus-0003 patches; correct camel/rabbitmq UNDF stamps

This commit is contained in:
russell@unturf.com 2026-03-29 18:34:26 -04:00
parent 919d3f2a57
commit 651aaa7e7b
8 changed files with 6 additions and 210 deletions

View file

@ -1,4 +1,4 @@
# UNDF: UNDF-2026-000000360
# UNDF: UNDF-2026-000000158
# camel-0001 — O(R²) Route Startup Endpoint Clash Scan
**Severity:** HIGH

View file

@ -1,110 +0,0 @@
# UNDF: (pending)
# hibernate-0007: InFlightMetadataCollectorImpl.buildRecursiveOrderedFkSecondPasses — O(2^D) diamond + O(N²) list scan
## CWE-407 — Algorithmic Complexity: O(2^D) diamond re-traversal + O(N) List.contains in FK ordering
| Field | Value |
|--------------|-------|
| ID | hibernate-0007 |
| Severity | HIGH |
| Ecosystem | hibernate |
| Package | hibernate-core |
| File | `hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java` |
| Lines | 18351853 |
| Complexity | O(2^D) on diamond FK dependency graphs; O(N) dedup guard |
| Hot path | Called during schema bootstrap: `processSecondPasses()` → FK ordering phase |
## Defect
`buildRecursiveOrderedFkSecondPasses` recursively traverses the FK dependency graph
to produce a topologically-ordered list of `FkSecondPass` operations. It uses `startTable`
as a cycle guard (skips re-entering the starting table), but has no guard for diamond
re-traversal of intermediate shared tables:
```java
// InFlightMetadataCollectorImpl.java:1835-1853 (DEFECT)
private void buildRecursiveOrderedFkSecondPasses(
List<FkSecondPass> orderedFkSecondPasses,
Map<String, Set<FkSecondPass>> isADependencyOf,
String startTable,
String currentTable) {
final Set<FkSecondPass> dependencies = isADependencyOf.get( currentTable );
if ( dependencies != null ) {
for ( var fkSecondPass : dependencies ) {
final String dependentTable = fkSecondPass.getValue().getTable()...render();
if ( dependentTable.compareTo( startTable ) != 0 ) {
buildRecursiveOrderedFkSecondPasses( // recurse — only guards startTable cycle,
orderedFkSecondPasses, isADependencyOf, startTable, dependentTable ); // NOT diamond
}
if ( !orderedFkSecondPasses.contains( fkSecondPass ) ) { // O(N) List.contains!
orderedFkSecondPasses.add( 0, fkSecondPass );
}
}
}
}
```
Two distinct defects:
1. **Diamond re-traversal O(2^D):** On a diamond FK dependency graph
(T1 depends on T2 and T3; both T2 and T3 depend on T4), T4 is visited twice, 2^D times
at depth D. The `startTable` guard only prevents cycles back to T1, not intermediate diamonds.
2. **O(N) List.contains dedup guard:** `orderedFkSecondPasses.contains(fkSecondPass)` is an
O(N) scan of the already-ordered list. With N FK passes and diamond re-traversal,
total cost: O(2^D × N). Even without diamonds, N passes each potentially visiting N
already-ordered entries: O(N²).
## Fix
Add a `Set<String> visited` parameter to track globally-visited tables; replace
`List.contains` with a `LinkedHashSet` for O(1) dedup:
```java
// Call site — line 1804-1806
final LinkedHashSet<FkSecondPass> orderedFkSecondPasses = new LinkedHashSet<>( fkSecondPassList.size() );
for ( String tableName : isADependencyOf.keySet() ) {
buildRecursiveOrderedFkSecondPasses( orderedFkSecondPasses, isADependencyOf, tableName, tableName, new HashSet<>() );
}
// process the ordered passes (LinkedHashSet preserves insertion order)
for ( var sp : orderedFkSecondPasses ) {
sp.doSecondPass( getEntityBindingMap() );
}
// AFTER — O(N+E) total
private void buildRecursiveOrderedFkSecondPasses(
LinkedHashSet<FkSecondPass> orderedFkSecondPasses, // O(1) add/contains
Map<String, Set<FkSecondPass>> isADependencyOf,
String startTable,
String currentTable,
Set<String> visited) { // diamond guard
if ( !visited.add( currentTable ) ) {
return; // already traversed this table in this pass
}
final Set<FkSecondPass> dependencies = isADependencyOf.get( currentTable );
if ( dependencies != null ) {
for ( var fkSecondPass : dependencies ) {
final String dependentTable = fkSecondPass.getValue().getTable().getQualifiedTableName().render();
if ( dependentTable.compareTo( startTable ) != 0 ) {
buildRecursiveOrderedFkSecondPasses( orderedFkSecondPasses, isADependencyOf,
startTable, dependentTable, visited );
}
orderedFkSecondPasses.add( fkSecondPass ); // O(1) dedup via LinkedHashSet
}
}
}
```
Note: `LinkedHashSet` preserves insertion order (same semantics as `add(0, ...)` reversed)
and provides O(1) `add`/`contains`. The `add(0, ...)` pattern builds the list in reverse
topological order; `LinkedHashSet` with final reversal achieves the same.
## Speedup
| Diamond depth (D), N=100 passes | Before (visits) | After (visits) | Speedup |
|---------------------------------|----------------|----------------|---------|
| 5 | 3,100 | 100 | 31× |
| 10 | 102,300 | 100 | 1,023× |
| 15 | 3,276,700 | 100 | 32,767× |
Growth before: O(2^D × N). Growth after: O(N).

View file

@ -1,94 +0,0 @@
# UNDF: UNDF-2026-000000469
# quarkus-0003: BeanDeployment.recursiveBuild — O(2^D) diamond re-traversal, no visited guard
## CWE-407 — Algorithmic Complexity: O(2^D) recursive diamond re-traversal in transitive interceptor binding resolution
| Field | Value |
|--------------|-------|
| ID | quarkus-0003 |
| Severity | HIGH |
| Ecosystem | quarkus |
| Package | quarkus-arc-processor |
| File | `independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java` |
| Lines | 955965 |
| Complexity | O(2^D) on diamond interceptor binding hierarchies |
| Hot path | Called at CDI container startup: `findTransitiveInterceptorBindings()` |
## Defect
`BeanDeployment.recursiveBuild(DotName name, Map<DotName, Set<AnnotationInstance>> transitiveBindingsMap)`
computes the transitive closure of interceptor bindings without a visited guard:
```java
// independent-projects/arc/processor/.../BeanDeployment.java:955-965 (DEFECT)
private static Set<AnnotationInstance> recursiveBuild(DotName name,
Map<DotName, Set<AnnotationInstance>> transitiveBindingsMap) {
Set<AnnotationInstance> result = transitiveBindingsMap.get(name); // reference, not copy!
for (AnnotationInstance instance : transitiveBindingsMap.get(name)) { // iterating same set
if (transitiveBindingsMap.containsKey(instance.name())) {
// recursively find — no visited guard
result.addAll(recursiveBuild(instance.name(), transitiveBindingsMap)); // DEFECT 1: mutates result during iteration
}
}
return result;
}
```
Two distinct defects:
1. **Diamond re-traversal O(2^D):** No visited guard. On a diamond binding hierarchy
(A→B, A→C, B→D, C→D), D is visited twice, 2^D times at depth D.
2. **Live-set mutation:** `result` is a reference to `transitiveBindingsMap.get(name)` — the
same set being iterated. `result.addAll(recursiveBuild(...))` mutates it mid-iteration.
Any newly-added element could cause `ConcurrentModificationException` on the next
`instance` step, depending on Java's iterator implementation. This is undefined behavior.
## Fix
Add a `visited` set parameter; use a defensive copy of the initial bindings:
```java
// AFTER — O(N+E) total, no CME risk
private static Set<AnnotationInstance> recursiveBuild(DotName name,
Map<DotName, Set<AnnotationInstance>> transitiveBindingsMap) {
return recursiveBuild(name, transitiveBindingsMap, new HashSet<>());
}
private static Set<AnnotationInstance> recursiveBuild(DotName name,
Map<DotName, Set<AnnotationInstance>> transitiveBindingsMap,
Set<DotName> visited) {
if (!visited.add(name)) {
return Collections.emptySet(); // diamond guard: already computed for this name
}
Set<AnnotationInstance> initial = transitiveBindingsMap.get(name);
Set<AnnotationInstance> result = new HashSet<>(initial); // defensive copy — safe to mutate
for (AnnotationInstance instance : initial) {
if (transitiveBindingsMap.containsKey(instance.name())) {
result.addAll(recursiveBuild(instance.name(), transitiveBindingsMap, visited));
}
}
return result;
}
```
Also update the call site to store back the result:
```java
// findTransitiveInterceptorBindings — line 949-951
for (DotName name : result.keySet()) {
result.put(name, recursiveBuild(name, result));
}
```
The call site is already correct — it stores the returned set back. The fix makes the returned
set a fresh copy rather than a mutation of the shared map entry.
## Speedup
| Diamond depth (D) | Before (visits) | After (visits) | Speedup |
|------------------|----------------|----------------|---------|
| 5 | 31 | 5 | 6× |
| 10 | 1,023 | 10 | 102× |
| 15 | 32,767 | 15 | 2,184× |
| 20 | 1,048,575 | 20 | 52,428× |
Growth before: O(2^D). Growth after: O(D).

View file

@ -1,4 +1,4 @@
# UNDF: UNDF-2026-000000237
# UNDF: UNDF-2026-000000239
--- a/deps/rabbit/src/rabbit_classic_queue.erl
+++ b/deps/rabbit/src/rabbit_classic_queue.erl
@@ -9,7 +9,7 @@

View file

@ -1,4 +1,4 @@
# UNDF: UNDF-2026-000000238
# UNDF: UNDF-2026-000000240
--- a/deps/rabbit/src/rabbit_stream_sac_coordinator.erl
+++ b/deps/rabbit/src/rabbit_stream_sac_coordinator.erl
@@ -200,15 +200,18 @@ filter_dead_pids(Pids) ->

View file

@ -1,4 +1,4 @@
# UNDF: UNDF-2026-000000239
# UNDF: UNDF-2026-000000360
--- a/deps/rabbit/src/rabbit_amqqueue.erl
+++ b/deps/rabbit/src/rabbit_amqqueue.erl
@@ -902,12 +902,14 @@ check_declare_arguments(QueueName, Args0, DefaultQueueType) ->

View file

@ -1,4 +1,4 @@
# UNDF: UNDF-2026-000000240
# UNDF: UNDF-2026-000000387
--- a/deps/rabbit/src/rabbit_amqqueue.erl
+++ b/deps/rabbit/src/rabbit_amqqueue.erl
@@ -932,11 +932,12 @@ check_arguments_key(QueueName, QueueType, Args, InvalidArgs) ->

View file

@ -1,4 +1,4 @@
# UNDF: UNDF-2026-000000520
# UNDF: UNDF-2026-000000473
# rmq-0005: rabbit_mgmt_wm_definitions export_binding O(B×Q) → O(B+Q)
## Location