java-topology/defects/netty-0002/patch/netty-0002-dns-resolve-dedup-list-contains.patch

36 lines
2.1 KiB
Diff

# UNDF: UNDF-2026-000000830
# 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 {