From 29308bfe000cc7b4af097a93f05e55cfe754b57d Mon Sep 17 00:00:00 2001 From: "russell@unturf.com" Date: Sun, 29 Mar 2026 17:14:17 -0400 Subject: [PATCH] =?UTF-8?q?quarkus-0003:=20BeanDeployment.recursiveBuild?= =?UTF-8?q?=20transitive=20bindings=20diamond=20O(2^D);=20count=20638?= =?UTF-8?q?=E2=86=92639?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UNDF-REGISTRY.json | 3 +- ...02-reinfer-visited-method-array-hashset.md | 1 + ...oy-transitivebindings-diamond-recursion.md | 85 +++++++++++++++++++ ...ark-0001-quic-streams-list-find-hashmap.md | 1 + 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 defects/quarkus/patch/quarkus-0003-beandeploy-transitivebindings-diamond-recursion.md diff --git a/UNDF-REGISTRY.json b/UNDF-REGISTRY.json index 700c778ed..edbd31fa3 100644 --- a/UNDF-REGISTRY.json +++ b/UNDF-REGISTRY.json @@ -579,5 +579,6 @@ "typescript-0003": "UNDF-2026-000000441", "kafka-0009": "UNDF-2026-000000451", "hibernate-0007": "UNDF-2026-000000464", - "threejs-0007": "UNDF-2026-000000468" + "threejs-0007": "UNDF-2026-000000468", + "quarkus-0003": "UNDF-2026-000000469" } diff --git a/defects/julia/patch/julia-0002-reinfer-visited-method-array-hashset.md b/defects/julia/patch/julia-0002-reinfer-visited-method-array-hashset.md index 566ef4b33..178600dac 100644 --- a/defects/julia/patch/julia-0002-reinfer-visited-method-array-hashset.md +++ b/defects/julia/patch/julia-0002-reinfer-visited-method-array-hashset.md @@ -1,3 +1,4 @@ +# UNDF: UNDF-2026-000000352 ## Classification | Field | Value | diff --git a/defects/quarkus/patch/quarkus-0003-beandeploy-transitivebindings-diamond-recursion.md b/defects/quarkus/patch/quarkus-0003-beandeploy-transitivebindings-diamond-recursion.md new file mode 100644 index 000000000..81f66331a --- /dev/null +++ b/defects/quarkus/patch/quarkus-0003-beandeploy-transitivebindings-diamond-recursion.md @@ -0,0 +1,85 @@ +# UNDF: UNDF-2026-000000469 +# UNDF: (pending) +# quarkus-0003: BeanDeployment.recursiveBuild — transitive binding traversal no visited set O(2^D) + +## CWE-407 — Algorithmic Complexity: Exponential Recursion on Diamond Annotation Hierarchy + +| Field | Value | +|--------------|-------| +| ID | quarkus-0003 | +| Severity | MEDIUM | +| Ecosystem | quarkus | +| Package | arc/processor | +| File | `independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java` | +| Lines | 955–964 | +| Complexity | O(2^D) where D = diamond depth in annotation hierarchy | +| Hot path | Called at application startup for every binding annotation | + +## Description + +`BeanDeployment.recursiveBuild(DotName name, Map> transitiveBindingsMap)` +traverses the transitive annotation binding graph recursively with no visited-set guard. + +On a diamond-shaped annotation hierarchy (annotation A meta-annotated with @B and @C; +both @B and @C meta-annotated with @D), the call tree is: + +``` +recursiveBuild(A) → recursiveBuild(B) → recursiveBuild(D) + → recursiveBuild(C) → recursiveBuild(D) ← D visited twice +``` + +At depth D, @D is visited 2^D times. At D=24: 16,777,216 redundant visits. + +```java +// BEFORE — O(2^D): no visited set — exponential on diamond annotation hierarchies +private static Set recursiveBuild(DotName name, + Map> transitiveBindingsMap) { + Set result = transitiveBindingsMap.get(name); + for (AnnotationInstance instance : transitiveBindingsMap.get(name)) { + if (transitiveBindingsMap.containsKey(instance.name())) { + result.addAll(recursiveBuild(instance.name(), transitiveBindingsMap)); + } + } + return result; +} +``` + +Note: `result` is the same reference as `transitiveBindingsMap.get(name)` — the function +modifies the map's values in-place during iteration, which also carries a +`ConcurrentModificationException` risk if the Set implementation doesn't tolerate modification. + +## Fix + +Add a `Set visited` parameter to guard against revisiting the same annotation node. + +```java +// AFTER — O(N+E): visited set prevents exponential re-traversal +for (DotName name : result.keySet()) { + result.put(name, recursiveBuild(name, result, new HashSet<>())); +} + +private static Set recursiveBuild(DotName name, + Map> transitiveBindingsMap, + Set visited) { + if (!visited.add(name)) { + return Collections.emptySet(); + } + Set result = new HashSet<>(transitiveBindingsMap.get(name)); + for (AnnotationInstance instance : transitiveBindingsMap.get(name)) { + if (transitiveBindingsMap.containsKey(instance.name())) { + result.addAll(recursiveBuild(instance.name(), transitiveBindingsMap, visited)); + } + } + return result; +} +``` + +## Speedup + +| Annotation depth (D) | Before (calls) | After (calls) | Speedup | +|---------------------|---------------|---------------|---------| +| 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). diff --git a/defects/wireshark/patch/wireshark-0001-quic-streams-list-find-hashmap.md b/defects/wireshark/patch/wireshark-0001-quic-streams-list-find-hashmap.md index 77aac2b6e..757874314 100644 --- a/defects/wireshark/patch/wireshark-0001-quic-streams-list-find-hashmap.md +++ b/defects/wireshark/patch/wireshark-0001-quic-streams-list-find-hashmap.md @@ -1,3 +1,4 @@ +# UNDF: UNDF-2026-000000341 ## Classification | Field | Value |