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-jdkim.git

commit 01e841d8b96234228113328bec7a3b37e9f04094
Author: Benoit TELLIER <[email protected]>
AuthorDate: Tue Nov 3 08:38:54 2026 +0100

    [FIX] SignatureRecordImpl: do not overflow the stack on long i=, q= and z=
    
    The patterns checking i=, q= and z= repeated an alternation greedily,
    which java.util.regex matches recursively, one frame per character: a
    z= copy or a q= value of a few KB threw a StackOverflowError. Being an
    Error, it got past the RuntimeException handling of the verifier and out
    of verify(). The repetitions are now possessive, as in TagValue: their
    alternatives are disjoint, so no backtracking is lost.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../james/jdkim/tagvalue/SignatureRecordImpl.java       | 16 +++++++++-------
 .../org/apache/james/jdkim/SignatureRecordImplTest.java | 17 +++++++++++++++++
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git 
a/main/src/main/java/org/apache/james/jdkim/tagvalue/SignatureRecordImpl.java 
b/main/src/main/java/org/apache/james/jdkim/tagvalue/SignatureRecordImpl.java
index 64bfd1a..2d62e51 100644
--- 
a/main/src/main/java/org/apache/james/jdkim/tagvalue/SignatureRecordImpl.java
+++ 
b/main/src/main/java/org/apache/james/jdkim/tagvalue/SignatureRecordImpl.java
@@ -109,10 +109,11 @@ public class SignatureRecordImpl extends TagValue 
implements SignatureRecord {
     }
 
     // SPEC (RFC 5321): Dot-string = Atom *("." Atom) ; Quoted-string = DQUOTE 
*QcontentSMTP DQUOTE,
-    // with the non-ASCII characters RFC 6531 adds to atext and qtextSMTP
-    private static final String ATEXT = 
"[A-Za-z0-9!#$%&'*+/=?^_`{|}~\\u0080-\\uFFFF-]+";
+    // with the non-ASCII characters RFC 6531 adds to atext and qtextSMTP.
+    // Possessive: a repeated group otherwise recurses once per character, 
overflowing the stack on long values.
+    private static final String ATEXT = 
"[A-Za-z0-9!#$%&'*+/=?^_`{|}~\\u0080-\\uFFFF-]++";
     private static final Pattern LOCAL_PART = Pattern.compile(
-            "|" + ATEXT + "(?:\\." + ATEXT + 
")*|\"(?:[\\x20\\x21\\x23-\\x5B\\x5D-\\x7E\\u0080-\\uFFFF]|\\\\[\\x20-\\x7E])*\"");
+            "|" + ATEXT + "(?:\\." + ATEXT + 
")*+|\"(?:[\\x20\\x21\\x23-\\x5B\\x5D-\\x7E\\u0080-\\uFFFF]|\\\\[\\x20-\\x7E])*+\"");
 
     /**
      * RFC 6376 section 3.5: checks the decoded i= value as [ Local-part ] "@" 
domain-name.
@@ -138,13 +139,14 @@ public class SignatureRecordImpl extends TagValue 
implements SignatureRecord {
     }
 
     // SPEC: sig-q-tag-method = "dns/txt" / x-sig-q-tag-type ["/" 
x-sig-q-tag-args], the type a
-    // hyphenated-word and the args a qp-hdr-value (dkim-safe-char but "|", or 
"=" HEX HEX)
+    // hyphenated-word and the args a qp-hdr-value (dkim-safe-char but "|", or 
"=" HEX HEX). Possessive, see LOCAL_PART.
     static final Pattern QUERY_METHOD = Pattern.compile(
-            
"[A-Za-z](?:[A-Za-z0-9-]*[A-Za-z0-9])?(?:/(?:[\\x21-\\x3A\\x3C\\x3E-\\x7B\\x7D\\x7E]|=[0-9A-F]{2})*)?");
+            
"[A-Za-z](?:[A-Za-z0-9-]*[A-Za-z0-9])?(?:/(?:[\\x21-\\x3A\\x3C\\x3E-\\x7B\\x7D\\x7E]|=[0-9A-F]{2})*+)?");
 
-    // SPEC: sig-z-tag-copy = hdr-name [FWS] ":" qp-hdr-value ; hdr-name = 
1*ftext (%d33-57 / %d59-126)
+    // SPEC: sig-z-tag-copy = hdr-name [FWS] ":" qp-hdr-value ; hdr-name = 
1*ftext (%d33-57 / %d59-126).
+    // Possessive, see LOCAL_PART.
     private static final Pattern COPIED_HEADER_FIELD = Pattern.compile(
-            "[\\x21-\\x39\\x3B-\\x7E]+[ 
\\t\\r\\n]*:(?:[\\x21-\\x3A\\x3C\\x3E-\\x7B\\x7D\\x7E]|=[0-9A-F]{2}|[ 
\\t\\r\\n])*");
+            "[\\x21-\\x39\\x3B-\\x7E]++[ 
\\t\\r\\n]*+:(?:[\\x21-\\x3A\\x3C\\x3E-\\x7B\\x7D\\x7E]|=[0-9A-F]{2}|[ 
\\t\\r\\n])*+");
 
     /**
      * RFC 6376 section 3.5: checks z= as sig-z-tag-copy *( "|" [FWS] 
sig-z-tag-copy ).
diff --git 
a/main/src/test/java/org/apache/james/jdkim/SignatureRecordImplTest.java 
b/main/src/test/java/org/apache/james/jdkim/SignatureRecordImplTest.java
index 0614da7..8f59319 100644
--- a/main/src/test/java/org/apache/james/jdkim/SignatureRecordImplTest.java
+++ b/main/src/test/java/org/apache/james/jdkim/SignatureRecordImplTest.java
@@ -449,4 +449,21 @@ public class SignatureRecordImplTest {
             System.clearProperty(TagValue.STRICT_VALIDATION_PROPERTY);
         }
     }
+
+    private static String repeat(String s, int times) {
+        StringBuilder sb = new StringBuilder(s.length() * times);
+        for (int k = 0; k < times; k++) {
+            sb.append(s);
+        }
+        return sb.toString();
+    }
+
+    @Test
+    public void longValuesDoNotOverflowTheStack() {
+        recordWithCopiedFields("Subject:" + repeat("a=20", 16384));
+        recordWithCopiedFields("Subject:" + repeat("a ", 32768) + "a");
+        recordWithQuery("x-foo/" + repeat("a=20", 16384));
+        recordWithIdentity(repeat("a.", 32768) + "[email protected]");
+        recordWithIdentity("\"" + repeat("a=20", 16384) + "\"@example.com");
+    }
 }


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

Reply via email to