This is an automated email from the ASF dual-hosted git repository.

chibenwa pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-jspf.git

commit 048417cccbad594ccb28476a155e5305f7416cf4
Author: Quan Tran <[email protected]>
AuthorDate: Wed Nov 4 23:31:58 2026 +0700

    [FIX] DNSServiceXBillImpl.getRecords: no unchecked exception from dnsjava
    
    dnsjava's Lookup throws ClassCastException on some malformed answers,
    as an UPDATE message holding a CNAME or DNAME without data. getRecords
    let it escape, although DNSService declares only TimeoutException: the
    executors now read it as a lookup error, but any other caller of
    getRecords got the unchecked exception instead of a TimeoutException.
    
    Report it as a TimeoutException, a DNS error, so a temperror (RFC 7208
    2.6.6: "a transient (generally DNS) error"), as Lookup does with
    TRY_AGAIN for the answers it rejects, and log it.
---
 .../apache/james/jspf/impl/DNSServiceXBillImpl.java  | 20 ++++++++++++++++++--
 .../apache/james/jspf/DNSServiceXBillImplTest.java   | 17 +++++++++++++++++
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git 
a/resolver/src/main/java/org/apache/james/jspf/impl/DNSServiceXBillImpl.java 
b/resolver/src/main/java/org/apache/james/jspf/impl/DNSServiceXBillImpl.java
index a0614cd..d92bfe5 100644
--- a/resolver/src/main/java/org/apache/james/jspf/impl/DNSServiceXBillImpl.java
+++ b/resolver/src/main/java/org/apache/james/jspf/impl/DNSServiceXBillImpl.java
@@ -199,6 +199,21 @@ public class DNSServiceXBillImpl implements DNSService {
         }
     }
 
+    /**
+     * @param query the lookup of the given request
+     * @return the answer of the lookup
+     * @throws TimeoutException on a DNS error, as dnsjava's 
ClassCastException on some malformed
+     *         answers: DNSService declares no other exception (RFC 7208 4.4)
+     */
+    private static Record[] run(Lookup query, Name name, int type) throws 
TimeoutException {
+        try {
+            return query.run();
+        } catch (RuntimeException e) {
+            LOGGER.warn("Unexpected error of the DNS lookup of {} (type {})", 
name, Type.string(type), e);
+            throw new TimeoutException(e.toString());
+        }
+    }
+
     /**
      * @return the records of the given type: an answer can hold others
      */
@@ -306,10 +321,11 @@ public class DNSServiceXBillImpl implements DNSService {
             LOGGER.debug("Start {}-Record lookup for : {}", 
recordTypeDescription, request.getHostname());
 
             // RFC 7208 4.3: a fully qualified name, not looked up under the 
search path of the host
-            Lookup query = new Lookup(Name.fromString(request.getHostname(), 
Name.root), dnsJavaType);
+            Name name = Name.fromString(request.getHostname(), Name.root);
+            Lookup query = new Lookup(name, dnsJavaType);
             query.setResolver(resolver);
 
-            Record[] rr = query.run();
+            Record[] rr = run(query, name, dnsJavaType);
             int queryResult = query.getResult();
             
 
diff --git 
a/resolver/src/test/java/org/apache/james/jspf/DNSServiceXBillImplTest.java 
b/resolver/src/test/java/org/apache/james/jspf/DNSServiceXBillImplTest.java
index 66abff9..ff02b21 100644
--- a/resolver/src/test/java/org/apache/james/jspf/DNSServiceXBillImplTest.java
+++ b/resolver/src/test/java/org/apache/james/jspf/DNSServiceXBillImplTest.java
@@ -25,6 +25,7 @@ import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.read.ListAppender;
 import org.apache.james.jspf.core.DNSRequest;
+import org.apache.james.jspf.core.exceptions.TimeoutException;
 import org.apache.james.jspf.helpers.AnsweringResolver;
 import org.apache.james.jspf.impl.DNSServiceXBillImpl;
 import org.junit.Test;
@@ -32,6 +33,7 @@ import org.slf4j.LoggerFactory;
 import org.xbill.DNS.CNAMERecord;
 import org.xbill.DNS.DClass;
 import org.xbill.DNS.Flags;
+import org.xbill.DNS.Lookup;
 import org.xbill.DNS.Message;
 import org.xbill.DNS.Name;
 import org.xbill.DNS.Record;
@@ -106,6 +108,21 @@ public class DNSServiceXBillImplTest {
         assertNull(DNSServiceXBillImpl.convertRecordsToList(answer));
     }
 
+    @Test(timeout = 10000)
+    public void 
getRecordsShouldReportADnsErrorForAnAnswerDnsjavaCannotProcess() throws 
Exception {
+        // opcode UPDATE, and the answer "example.com CNAME" of RDLENGTH 0: 
dnsjava's Lookup throws ClassCastException
+        byte[] message = 
Base64.getDecoder().decode("AAErAAABAAEAAAAAB2V4YW1wbGUDY29tAAAQAAHADAAFAAAAAA5RAABj");
+        DNSServiceXBillImpl dns = new DNSServiceXBillImpl(new 
AnsweringResolver(message));
+        Lookup.getDefaultCache(DClass.IN).clearCache();
+
+        try {
+            dns.getRecords(new DNSRequest("example.com", DNSRequest.TXT));
+            fail("the lookup should fail");
+        } catch (TimeoutException e) {
+            // DNSService declares only TimeoutException: a DNS error (RFC 
7208 4.4)
+        }
+    }
+
     @Test(timeout = 10000)
     public void 
getRecordsAsyncShouldEndALookupWhoseAnswerHoldsACnameOfAnotherName() throws 
Exception {
         AnsweringResolver resolver = new 
AnsweringResolver(Base64.getDecoder().decode(CNAME_OF_THE_ROOT));


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to