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 0d4bb9430a47743439ff0dd2512535384e90bde6
Author: Quan Tran <[email protected]>
AuthorDate: Fri Oct 30 16:30:55 2026 +0700

    [FIX] ip4/ip6 mechanisms: an overflowing CIDR length is a permerror
    
    The regex accepts any number of digits as the CIDR length, so
    ip4:192.0.2.1/4294967296 or ip6:2001:db8::/99999999999 made
    Integer.parseInt throw NumberFormatException out of the parser: the
    check ended as neutral instead of permerror (RFC 7208 5.6).
    
    Reject a length of more than 3 digits before parsing it, as /33 is.
---
 .../org/apache/james/jspf/terms/IP4Mechanism.java    |  4 ++++
 .../org/apache/james/jspf/SPFExecutorBaseTest.java   | 20 ++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git 
a/resolver/src/main/java/org/apache/james/jspf/terms/IP4Mechanism.java 
b/resolver/src/main/java/org/apache/james/jspf/terms/IP4Mechanism.java
index 44c17f6..b483255 100644
--- a/resolver/src/main/java/org/apache/james/jspf/terms/IP4Mechanism.java
+++ b/resolver/src/main/java/org/apache/james/jspf/terms/IP4Mechanism.java
@@ -68,6 +68,10 @@ public class IP4Mechanism extends GenericMechanism {
         int maskLength = getMaxCidr();
         if (params.groupCount() >= 2 && params.group(2) != null) {
             String maskLengthString = params.group(2);
+            // the regex accepts any number of digits: more than 3 are 
invalid, and could overflow an int
+            if (maskLengthString.length() > 3) {
+                throw new PermErrorException("Invalid CIDR: " + 
maskLengthString);
+            }
             maskLength = Integer.parseInt(maskLengthString);
 
             if (maskLength > getMaxCidr() || (maskLengthString.length() > 1 && 
maskLengthString.startsWith("0"))) {
diff --git 
a/resolver/src/test/java/org/apache/james/jspf/SPFExecutorBaseTest.java 
b/resolver/src/test/java/org/apache/james/jspf/SPFExecutorBaseTest.java
index 1e7ac25..f56e270 100644
--- a/resolver/src/test/java/org/apache/james/jspf/SPFExecutorBaseTest.java
+++ b/resolver/src/test/java/org/apache/james/jspf/SPFExecutorBaseTest.java
@@ -58,6 +58,12 @@ public abstract class SPFExecutorBaseTest {
         return Paths.get(zonesDir, zoneFile).toAbsolutePath().toString();
     }
 
+    private SPFResult checkRecord(String hostname, String record, String 
ipAddress) throws IOException {
+        FakeResolver fakeResolver = new FakeResolver();
+        fakeResolver.addRecord(new TXTRecord(Name.fromString(hostname + "."), 
DClass.IN, 30L, record));
+        return createCustomSPF(new 
DNSServiceXBillImpl(fakeResolver)).checkSPF(ipAddress, "a_user@" + hostname, 
hostname);
+    }
+
     @Test
     public void test() {
         SPF spf = createSPF();
@@ -450,4 +456,18 @@ public abstract class SPFExecutorBaseTest {
 
         assertEquals(SPFErrorConstants.PASS_CONV, result.getResult());
     }
+
+    @Test(timeout = 10000)
+    public void shouldReturnPermErrorOnIp4CidrOverflowingAnInt() throws 
IOException {
+        SPFResult result = checkRecord("ip4CidrOverflow.spfexecutor.fake", 
"v=spf1 ip4:192.0.2.1/4294967296 -all", "1.2.3.4");
+
+        assertEquals(SPFErrorConstants.PERM_ERROR_CONV, result.getResult());
+    }
+
+    @Test(timeout = 10000)
+    public void shouldReturnPermErrorOnIp6CidrOverflowingAnInt() throws 
IOException {
+        SPFResult result = checkRecord("ip6CidrOverflow.spfexecutor.fake", 
"v=spf1 ip6:2001:db8::/99999999999 -all", "1.2.3.4");
+
+        assertEquals(SPFErrorConstants.PERM_ERROR_CONV, result.getResult());
+    }
 }


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

Reply via email to