This is an automated email from the ASF dual-hosted git repository. reta pushed a commit to branch 3.6.x-fixes in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 2b9d8af7e5e86b85a33ab22cffdba10b0c951528 Author: Andriy Redko <[email protected]> AuthorDate: Tue Sep 1 17:16:37 2026 -0400 Make sure attachment-max-header-size property is respected for repeated and multi-line headers (#3425) (cherry picked from commit 1f74aa7943b704532fecdb61190dca87e9b63313) --- .../cxf/attachment/AttachmentDeserializerUtil.java | 17 +++- .../cxf/attachment/AttachmentDeserializerTest.java | 92 ++++++++++++++++++++++ 2 files changed, 106 insertions(+), 3 deletions(-) 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 c74d70c2962..155bc4d9597 100644 --- a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializerUtil.java +++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializerUtil.java @@ -95,11 +95,17 @@ final class AttachmentDeserializerUtil { // preserve the line break and append the continuation buffer.append("\r\n"); buffer.append(b); + + if (buffer.length() > maxHeaderLength) { + LOG.fine("The attachment header size has exceeded the configured parameter: " + + maxHeaderLength); + throw new HeaderSizeExceededException(); + } } } else { // if we have a line pending in the buffer, flush it if (buffer.length() > 0) { - addHeaderLine(heads, buffer, maxHeadersCount); + addHeaderLine(heads, buffer, maxHeadersCount, maxHeaderLength); buffer.setLength(0); } // add this to the accumulator @@ -109,7 +115,7 @@ final class AttachmentDeserializerUtil { // if we have a line pending in the buffer, flush it if (buffer.length() > 0) { - addHeaderLine(heads, buffer, maxHeadersCount); + addHeaderLine(heads, buffer, maxHeadersCount, maxHeaderLength); } return heads; } @@ -144,7 +150,7 @@ final class AttachmentDeserializerUtil { } private static void addHeaderLine(Map<String, List<String>> heads, StringBuilder line, - int maxHeadersCount) throws IOException { + int maxHeadersCount, int maxHeaderLength) throws IOException { // null lines are a nop final int size = line.length(); if (size == 0) { @@ -174,6 +180,11 @@ final class AttachmentDeserializerUtil { throw new IOException("The attachment contains more headers than are permitted"); } List<String> v = heads.computeIfAbsent(name, k -> new ArrayList<>(1)); + final int headerSize = v.stream().mapToInt(String::length).sum(); + if ((headerSize + value.length()) > maxHeaderLength) { + LOG.fine("The attachment header size has exceeded the configured parameter: " + maxHeaderLength); + throw new HeaderSizeExceededException(); + } 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 c5e8b145312..b9f14b2bc38 100644 --- a/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java +++ b/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -713,7 +714,98 @@ public class AttachmentDeserializerTest { assertThrows("Failure expected on too many attachment headers", IOException.class, () -> ad.initializeAttachments()); } + + @Test + public void testAttachmentHeaderSize() throws Exception { + final Random random = new Random(); + + StringBuilder sb = new StringBuilder(10000); + // Add many attachment headers + sb.append("------=_Part_34950_1098328613.1263781527359\n"); + sb.append("Header:") + .append(random.ints('a', 'z') + .limit(500) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)) + .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 large header value", HeaderSizeExceededException.class, + () -> ad.initializeAttachments()); + } + + @Test + public void testAttachmentRepeatedHeaderSize() throws Exception { + final Random random = new Random(); + + StringBuilder sb = new StringBuilder(10000); + // Add many attachment headers + sb.append("------=_Part_34950_1098328613.1263781527359\n"); + sb.append("Header:") + .append(random.ints('a', 'z') + .limit(200) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)) + .append('\n'); + sb.append("Header:") + .append(random.ints('a', 'z') + .limit(200) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)) + .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 large header value", HeaderSizeExceededException.class, + () -> ad.initializeAttachments()); + } + @Test + public void testAttachmentMultiLineHeaderSize() throws Exception { + final Random random = new Random(); + + StringBuilder sb = new StringBuilder(10000); + // Add many attachment headers + sb.append("------=_Part_34950_1098328613.1263781527359\n"); + sb.append("Header:") + .append(random.ints('a', 'z') + .limit(200) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)) + .append('\n') + .append('\t') + .append(random.ints('a', 'z') + .limit(200) + .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)) + .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 large header value", HeaderSizeExceededException.class, + () -> ad.initializeAttachments()); + } + @Test public void testManyAttachmentsDataHandlerIterator() throws Exception { prepareAttachments();
