diff --git a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsResolveContext.java b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsResolveContext.java index f625be975c..88fcdee70a 100644 --- a/resolver-dns/src/main/java/io/netty/resolver/dns/DnsResolveContext.java +++ b/resolver-dns/src/main/java/io/netty/resolver/dns/DnsResolveContext.java @@ -695,10 +695,17 @@ abstract class DnsResolveContext { continue; } + // 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. if (finalResult == null) { finalResult = new ArrayList(8); + finalResult.add(converted); + } else if (!finalResult.contains(converted)) { + finalResult.add(converted); } - finalResult.add(converted); cache(hostname, additionals, r, converted); found = true; diff --git a/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java b/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java index 05801a176d..0d31321332 100644 --- a/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java +++ b/resolver-dns/src/test/java/io/netty/resolver/dns/DnsNameResolverTest.java @@ -2539,4 +2539,50 @@ public class DnsNameResolverTest { } return list; } + + @Test + public void testNotIncludeDuplicates() throws IOException { + final String name = "netty.io"; + final String ipv4Addr = "1.2.3.4"; + TestDnsServer dnsServer2 = new TestDnsServer(new RecordStore() { + @Override + public Set getRecords(QuestionRecord question) { + Set records = new LinkedHashSet(4); + String qName = question.getDomainName().toLowerCase(); + if (qName.equals(name)) { + records.add(new TestDnsServer.TestResourceRecord( + qName, RecordType.CNAME, + Collections.singletonMap( + DnsAttribute.DOMAIN_NAME.toLowerCase(), "cname.netty.io"))); + records.add(new TestDnsServer.TestResourceRecord(qName, + RecordType.A, Collections.singletonMap( + DnsAttribute.IP_ADDRESS.toLowerCase(), ipv4Addr))); + } else { + records.add(new TestDnsServer.TestResourceRecord(qName, + RecordType.A, Collections.singletonMap( + DnsAttribute.IP_ADDRESS.toLowerCase(), ipv4Addr))); + } + return records; + } + }); + dnsServer2.start(); + DnsNameResolver resolver = null; + try { + DnsNameResolverBuilder builder = newResolver() + .recursionDesired(true) + .maxQueriesPerResolve(16) + .nameServerProvider(new SingletonDnsServerAddressStreamProvider(dnsServer2.localAddress())); + builder.resolvedAddressTypes(ResolvedAddressTypes.IPV4_ONLY); + + resolver = builder.build(); + List resolvedAddresses = resolver.resolveAll(name).syncUninterruptibly().getNow(); + assertEquals(Collections.singletonList(InetAddress.getByAddress(name, new byte[] { 1, 2, 3, 4 })), + resolvedAddresses); + } finally { + dnsServer2.stop(); + if (resolver != null) { + resolver.close(); + } + } + } }