tomcat-0001/hibernate-orm-0001/netty-0001/netty-0002: 4 new CWE-407 defects

tomcat-0001: WebSocket getNegotiatedSubprotocol List.contains O(R×S) MEDIUM 52x
hibernate-orm-0001: FK ordering buildRecursiveOrderedFkSecondPasses List.contains O(N²) HIGH 2.8x
netty-0001: ALPN select/selected List.contains O(S×P) MEDIUM 26x
netty-0002: DnsResolveContext dedup ArrayList.contains O(R²) MEDIUM 30x

All 4/4 unit tests PASS.
This commit is contained in:
russell@unturf.com 2026-03-30 13:55:21 -04:00
parent 7f2c2a1a36
commit 32cbeb5dcb
8 changed files with 531 additions and 0 deletions

View file

@ -0,0 +1,35 @@
# UNDF:
# Defect: netty-0002
# Component: io.netty.resolver.dns.DnsResolveContext
# Pattern: CWE-407 — ArrayList.contains() for DNS result deduplication
# Severity: MEDIUM
# Complexity: O(R²) per DNS resolution → O(R) with companion HashSet
# Description: DnsResolveContext accumulates resolved addresses into
# finalResult (an ArrayList) and calls finalResult.contains(converted)
# to deduplicate. With R results, this is O(R²). The code comment
# acknowledges HashSet would be ideal but chooses ArrayList to avoid
# "extra memory copy and allocations" — but the O(R²) scan cost
# dominates for responses with many records (e.g., CDN domains with
# 50+ A records). Fix: maintain a companion HashSet for O(1) dedup
# while keeping the ArrayList for ordered result access.
--- a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsResolveContext.java
+++ b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsResolveContext.java
@@ -905,10 +905,11 @@
if (!promise.isDone()) {
- // We want to ensure we do not have duplicates in finalResult as this may be unexpected.
- //
- // While using a LinkedHashSet or HashSet may sound like the perfect fit for this we will use an
- // ArrayList here as duplicates should be found quite unfrequently in the wild and we dont want to pay
- // for the extra memory copy and allocations in this cases later on.
+ // Deduplicate with a companion HashSet for O(1) membership test.
+ // The ArrayList is retained for ordered access.
if (finalResult == null) {
finalResult = new ArrayList<T>(8);
+ finalResultSet = new HashSet<T>(8);
finalResult.add(converted);
- } else if (isDuplicateAllowed() || !finalResult.contains(converted)) {
+ finalResultSet.add(converted);
+ } else if (isDuplicateAllowed() || !finalResultSet.contains(converted)) {
finalResult.add(converted);
+ finalResultSet.add(converted);
} else {