This is an automated email from the ASF dual-hosted git repository.
reta pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/main by this push:
new cc0ef249b7c Add limit to the maximum number of attachment headers to
be collected (#3159)
cc0ef249b7c is described below
commit cc0ef249b7cba0be484c62b17445372d31fcea10
Author: Andriy Redko <[email protected]>
AuthorDate: Tue Jun 2 11:36:41 2026 -0400
Add limit to the maximum number of attachment headers to be collected
(#3159)
---
.../attachment/AttachmentBoundaryDeserializer.java | 8 +++++++-
.../cxf/attachment/AttachmentDeserializer.java | 17 ++++++++++++++--
.../cxf/attachment/AttachmentDeserializerUtil.java | 14 +++++++++----
.../cxf/attachment/AttachmentDeserializerTest.java | 23 ++++++++++++++++++++++
4 files changed, 55 insertions(+), 7 deletions(-)
diff --git
a/core/src/main/java/org/apache/cxf/attachment/AttachmentBoundaryDeserializer.java
b/core/src/main/java/org/apache/cxf/attachment/AttachmentBoundaryDeserializer.java
index 72675a0e5cd..e7bdc7d616d 100644
---
a/core/src/main/java/org/apache/cxf/attachment/AttachmentBoundaryDeserializer.java
+++
b/core/src/main/java/org/apache/cxf/attachment/AttachmentBoundaryDeserializer.java
@@ -38,12 +38,17 @@ public class AttachmentBoundaryDeserializer {
private static final int PUSHBACK_AMOUNT = 2048;
private final int maxHeaderLength;
+ private final int maxHeadersCount;
private final Message message;
public AttachmentBoundaryDeserializer(Message message) {
this.message = message;
this.maxHeaderLength = MessageUtils.getContextualInteger(message,
AttachmentDeserializer.ATTACHMENT_MAX_HEADER_SIZE,
AttachmentDeserializer.DEFAULT_MAX_HEADER_SIZE);
+ // Get the maximum headers count
+ this.maxHeadersCount = MessageUtils.getContextualInteger(message,
+ AttachmentDeserializer.ATTACHMENT_HEADERS_MAX_COUNT,
+ AttachmentDeserializer.DEFAULT_ATTACHMENT_HEADERS_MAX_COUNT);
}
public Attachment read(InputStream body) throws IOException {
@@ -60,7 +65,8 @@ public class AttachmentBoundaryDeserializer {
throw new IOException("Couldn't find MIME boundary: " +
boundaryString);
}
- Map<String, List<String>> ih =
AttachmentDeserializerUtil.loadPartHeaders(stream, maxHeaderLength);
+ final Map<String, List<String>> ih = AttachmentDeserializerUtil
+ .loadPartHeaders(stream, maxHeaderLength, maxHeadersCount);
String val = AttachmentUtil.getHeader(ih, "Content-Transfer-Encoding");
MimeBodyPartInputStream mmps = new MimeBodyPartInputStream(stream,
boundary, PUSHBACK_AMOUNT);
diff --git
a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
index d3b87411eac..d5c6409cb56 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
@@ -67,6 +67,13 @@ public class AttachmentDeserializer {
*/
public static final String ATTACHMENT_MAX_COUNT = "attachment-max-count";
+ /**
+ * The maximum number of attachment headers permitted in a message. The
default is 500.
+ */
+ public static final String ATTACHMENT_HEADERS_MAX_COUNT =
"attachment-headers-max-count";
+ public static final int DEFAULT_ATTACHMENT_HEADERS_MAX_COUNT =
+
SystemPropertyAction.getInteger("org.apache.cxf.attachment-max-headers-count",
500);
+
/**
* The maximum MIME Header Length. The default is 300.
*/
@@ -102,6 +109,7 @@ public class AttachmentDeserializer {
private List<String> supportedTypes;
private int maxHeaderLength = DEFAULT_MAX_HEADER_SIZE;
+ private int maxHeadersCount = DEFAULT_ATTACHMENT_HEADERS_MAX_COUNT;
public AttachmentDeserializer(Message message) {
this(message, Collections.singletonList("multipart/related"));
@@ -114,6 +122,9 @@ public class AttachmentDeserializer {
// Get the maximum Header length from configuration
maxHeaderLength = MessageUtils.getContextualInteger(message,
ATTACHMENT_MAX_HEADER_SIZE,
DEFAULT_MAX_HEADER_SIZE);
+ // Get the maximum headers count
+ maxHeadersCount = MessageUtils.getContextualInteger(message,
ATTACHMENT_HEADERS_MAX_COUNT,
+
DEFAULT_ATTACHMENT_HEADERS_MAX_COUNT);
}
public void initializeAttachments() throws IOException {
@@ -160,7 +171,8 @@ public class AttachmentDeserializer {
throw new IOException("Couldn't find MIME boundary: " +
boundaryString);
}
- Map<String, List<String>> ih =
AttachmentDeserializerUtil.loadPartHeaders(stream, maxHeaderLength);
+ final Map<String, List<String>> ih = AttachmentDeserializerUtil
+ .loadPartHeaders(stream, maxHeaderLength, maxHeadersCount);
message.put(ATTACHMENT_PART_HEADERS, ih);
String val = AttachmentUtil.getHeader(ih, "Content-Type", "; ");
if (!StringUtils.isEmpty(val)) {
@@ -225,7 +237,8 @@ public class AttachmentDeserializer {
}
stream.unread(v);
- Map<String, List<String>> headers =
AttachmentDeserializerUtil.loadPartHeaders(stream, maxHeaderLength);
+ final Map<String, List<String>> headers = AttachmentDeserializerUtil
+ .loadPartHeaders(stream, maxHeaderLength, maxHeadersCount);
return (AttachmentImpl)createAttachment(headers);
}
diff --git
a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializerUtil.java
b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializerUtil.java
index 98ee9a468c2..c74d70c2962 100644
---
a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializerUtil.java
+++
b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializerUtil.java
@@ -80,7 +80,8 @@ final class AttachmentDeserializerUtil {
}
- static Map<String, List<String>> loadPartHeaders(InputStream in, int
maxHeaderLength) throws IOException {
+ static Map<String, List<String>> loadPartHeaders(InputStream in, int
maxHeaderLength,
+ int maxHeadersCount) throws IOException {
StringBuilder buffer = new StringBuilder(128);
StringBuilder b = new StringBuilder(128);
Map<String, List<String>> heads = new
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
@@ -98,7 +99,7 @@ final class AttachmentDeserializerUtil {
} else {
// if we have a line pending in the buffer, flush it
if (buffer.length() > 0) {
- addHeaderLine(heads, buffer);
+ addHeaderLine(heads, buffer, maxHeadersCount);
buffer.setLength(0);
}
// add this to the accumulator
@@ -108,7 +109,7 @@ final class AttachmentDeserializerUtil {
// if we have a line pending in the buffer, flush it
if (buffer.length() > 0) {
- addHeaderLine(heads, buffer);
+ addHeaderLine(heads, buffer, maxHeadersCount);
}
return heads;
}
@@ -142,7 +143,8 @@ final class AttachmentDeserializerUtil {
return buffer.length() != 0;
}
- private static void addHeaderLine(Map<String, List<String>> heads,
StringBuilder line) {
+ private static void addHeaderLine(Map<String, List<String>> heads,
StringBuilder line,
+ int maxHeadersCount) throws IOException {
// null lines are a nop
final int size = line.length();
if (size == 0) {
@@ -167,6 +169,10 @@ final class AttachmentDeserializerUtil {
}
value = line.substring(separator);
}
+
+ if (heads.size() >= maxHeadersCount) {
+ throw new IOException("The attachment contains more headers than
are permitted");
+ }
List<String> v = heads.computeIfAbsent(name, k -> new ArrayList<>(1));
v.add(value);
}
diff --git
a/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
b/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
index 70657184808..eec76dbba9c 100644
---
a/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
+++
b/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
@@ -20,6 +20,7 @@ package org.apache.cxf.attachment;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.nio.charset.StandardCharsets;
@@ -667,6 +668,28 @@ public class AttachmentDeserializerTest {
ins.close();
}
+ @Test
+ public void testManyAttachmentHeaders() throws Exception {
+ StringBuilder sb = new StringBuilder(10000);
+ // Add many attachment headers
+ sb.append("------=_Part_34950_1098328613.1263781527359\n");
+ IntStream.range(0, 1000).forEach(i ->
sb.append("Header-").append(i).append(": foo").append(i).append('\n'));
+ sb.append("Content-Type: text/xml; charset=UTF-8\n")
+ .append("Content-Transfer-Encoding: binary\n")
+ .append("Content-Id:
<318731183421.1263781527359.IBM.WEBSERVICES@auhpap02>\n")
+ .append('\n')
+ .append("<envelope/>\n");
+
+ msg = new MessageImpl();
+ msg.setContent(InputStream.class, new
ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8)));
+ msg.put(Message.CONTENT_TYPE, "multipart/related");
+ AttachmentDeserializer ad = new AttachmentDeserializer(msg);
+
+ assertThrows("Failure expected on too many attachment headers",
IOException.class,
+ () -> ad.initializeAttachments());
+ }
+
+
@Test
public void testManyAttachments() throws Exception {
StringBuilder sb = new StringBuilder(1000);