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

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


The following commit(s) were added to refs/heads/master by this push:
     new 5616ba58 [ENHANCEMENT] Improve RawField::checkLineBreaks
5616ba58 is described below

commit 5616ba583c7b4191222e2f16bf2cdc7fa08bd2fa
Author: Benoit TELLIER <[email protected]>
AuthorDate: Wed Oct 28 21:50:39 2026 +0100

    [ENHANCEMENT] Improve RawField::checkLineBreaks
---
 .../org/apache/james/mime4j/stream/RawField.java   | 32 +++++++++-----
 .../apache/james/mime4j/stream/RawFieldTest.java   | 48 +++++++++++++++++++--
 .../mime4j/message/DefaultMessageWriterTest.java   | 49 +++++++++++++++++++++-
 3 files changed, 113 insertions(+), 16 deletions(-)

diff --git a/core/src/main/java/org/apache/james/mime4j/stream/RawField.java 
b/core/src/main/java/org/apache/james/mime4j/stream/RawField.java
index 0f7c9dbd..3393a14c 100644
--- a/core/src/main/java/org/apache/james/mime4j/stream/RawField.java
+++ b/core/src/main/java/org/apache/james/mime4j/stream/RawField.java
@@ -57,22 +57,32 @@ public final class RawField implements Field {
     public RawField(String name, String body) {
         this(null, -1, name, body);
 
-        int pos = 0;
+        if (body != null) {
+            checkLineBreaks(body);
+        }
+    }
 
-        while (true) {
-            pos = body.indexOf('\r', pos);
-            if (pos < 0) {
-                break;
+    /**
+     * Only folds (CRLF followed by SP or HTAB) are allowed: a bare CR, a bare 
LF or a CRLF not
+     * followed by whitespace (including at the end of the body) would start a 
new header line or
+     * end the header block once written.
+     */
+    private static void checkLineBreaks(String body) {
+        int length = body.length();
+        for (int pos = 0; pos < length; pos++) {
+            char c = body.charAt(pos);
+            if (c == '\n') {
+                throw new IllegalArgumentException("Injection of un-encoded 
line breaks inside header field could be assimilated to header injection");
             }
-            if (pos < body.length() + 2) {
-                if (body.charAt(pos + 1) != '\n') {
-                    throw new IllegalArgumentException("Injection of 
un-encoded line breaks inside header field could be assimilated to header 
injection");
-                }
-                if (pos != body.length() - 2 && !isSpace(body, pos + 2)) {
+            if (c == '\r') {
+                if (pos + 2 >= length
+                    || body.charAt(pos + 1) != '\n'
+                    || !isSpace(body, pos + 2)) {
                     throw new IllegalArgumentException("Injection of 
un-encoded line breaks inside header field could be assimilated to header 
injection");
                 }
+                // Skip the LF of the fold
+                pos++;
             }
-            pos ++;
         }
     }
 
diff --git 
a/core/src/test/java/org/apache/james/mime4j/stream/RawFieldTest.java 
b/core/src/test/java/org/apache/james/mime4j/stream/RawFieldTest.java
index 775c92dd..49849d08 100644
--- a/core/src/test/java/org/apache/james/mime4j/stream/RawFieldTest.java
+++ b/core/src/test/java/org/apache/james/mime4j/stream/RawFieldTest.java
@@ -80,8 +80,8 @@ public class RawFieldTest {
     }
 
     @Test
-    public void shouldAcceptCRLFTerminatedHeader() {
-        assertThatCode(() -> new RawField("Name", 
"Value\r\n")).doesNotThrowAnyException();
+    public void shouldRejectCRLFTerminatedHeader() {
+        assertThatThrownBy(() -> new RawField("Name", 
"Value\r\n")).isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
@@ -95,8 +95,48 @@ public class RawFieldTest {
     }
 
     @Test
-    public void shouldAcceptOnlyDelimiter() {
-        assertThatCode(() -> new RawField("Name", 
"\r\n")).doesNotThrowAnyException();
+    public void shouldRejectOnlyDelimiter() {
+        assertThatThrownBy(() -> new RawField("Name", 
"\r\n")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void shouldRejectBareLF() {
+        assertThatThrownBy(() -> new RawField("Name", "x\nBcc: 
[email protected]")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void shouldRejectBareLFBeforeSpace() {
+        assertThatThrownBy(() -> new RawField("Name", "x\n 
y")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void shouldRejectOnlyLF() {
+        assertThatThrownBy(() -> new RawField("Name", 
"\n\n")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void shouldRejectBareCR() {
+        assertThatThrownBy(() -> new RawField("Name", "x\rBcc: 
[email protected]")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void shouldRejectTrailingCR() {
+        assertThatThrownBy(() -> new RawField("Name", 
"Value\r")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void shouldRejectCRLFLF() {
+        assertThatThrownBy(() -> new RawField("Name", 
"Value\r\n\n")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void shouldRejectFoldFollowedByEmptyLine() {
+        assertThatThrownBy(() -> new RawField("Name", "Value\r\n 
a\r\n\r\nbody")).isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void shouldAcceptMultipleFolds() {
+        assertThatCode(() -> new RawField("Name", "a\r\n 
b\r\n\tc")).doesNotThrowAnyException();
     }
 
 
diff --git 
a/dom/src/test/java/org/apache/james/mime4j/message/DefaultMessageWriterTest.java
 
b/dom/src/test/java/org/apache/james/mime4j/message/DefaultMessageWriterTest.java
index 19eafe24..9409b801 100644
--- 
a/dom/src/test/java/org/apache/james/mime4j/message/DefaultMessageWriterTest.java
+++ 
b/dom/src/test/java/org/apache/james/mime4j/message/DefaultMessageWriterTest.java
@@ -23,7 +23,12 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import org.apache.james.mime4j.Charsets;
+import java.util.Collections;
+
 import org.apache.james.mime4j.dom.Message;
+import org.apache.james.mime4j.dom.address.Mailbox;
+import org.apache.james.mime4j.field.Fields;
+import org.apache.james.mime4j.stream.RawField;
 import org.junit.Test;
 
 public class DefaultMessageWriterTest {
@@ -58,4 +63,46 @@ public class DefaultMessageWriterTest {
             .isInstanceOf(IllegalArgumentException.class);
     }
 
-}
\ No newline at end of file
+    @Test
+    public void rawFieldShouldRejectBareLF() {
+        assertThatThrownBy(() -> new RawField("X-Custom", "x\nBcc: 
[email protected]"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void rawFieldShouldRejectTrailingCRLF() {
+        assertThatThrownBy(() -> new RawField("X-Custom", "\r\n"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void messageIdShouldRejectTrailingCRLF() {
+        assertThatThrownBy(() -> Fields.messageId("<a@b>\r\n"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void messageIdShouldRejectBareLF() {
+        assertThatThrownBy(() -> Fields.messageId("\n\n"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void fromShouldRejectBareLFInDisplayName() {
+        assertThatThrownBy(() -> Fields.from(new Mailbox("\n!", "", "")))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void contentTypeShouldRejectBareLFInParameter() {
+        assertThatThrownBy(() -> Fields.contentType("text/plain", 
Collections.singletonMap("name", "\n")))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+    @Test
+    public void contentDispositionShouldRejectBareLFInFilename() {
+        assertThatThrownBy(() -> Fields.contentDisposition("attachment", 
"\n!"))
+            .isInstanceOf(IllegalArgumentException.class);
+    }
+
+}


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

Reply via email to