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 155bc4d9597..c2d4d2bffed 100644 --- a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializerUtil.java +++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializerUtil.java @@ -85,6 +85,7 @@ static Map> loadPartHeaders(InputStream in, int maxHeaderLe StringBuilder buffer = new StringBuilder(128); StringBuilder b = new StringBuilder(128); Map> heads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + int totalHeadersCollected = 0; // loop until we hit the end or a null line while (readLine(in, b, maxHeaderLength)) { @@ -105,7 +106,12 @@ static Map> loadPartHeaders(InputStream in, int maxHeaderLe } else { // if we have a line pending in the buffer, flush it if (buffer.length() > 0) { - addHeaderLine(heads, buffer, maxHeadersCount, maxHeaderLength); + if (addHeaderLine(heads, buffer, maxHeadersCount, maxHeaderLength)) { + totalHeadersCollected += 1; + if (totalHeadersCollected > maxHeadersCount) { + throw new IOException("The attachment contains more headers than are permitted"); + } + } buffer.setLength(0); } // add this to the accumulator @@ -114,8 +120,11 @@ static Map> loadPartHeaders(InputStream in, int maxHeaderLe } // if we have a line pending in the buffer, flush it - if (buffer.length() > 0) { - addHeaderLine(heads, buffer, maxHeadersCount, maxHeaderLength); + if (buffer.length() > 0 && addHeaderLine(heads, buffer, maxHeadersCount, maxHeaderLength)) { + totalHeadersCollected += 1; + if (totalHeadersCollected > maxHeadersCount) { + throw new IOException("The attachment contains more headers than are permitted"); + } } return heads; } @@ -149,12 +158,12 @@ private static boolean readLine(InputStream in, StringBuilder buffer, int maxHea return buffer.length() != 0; } - private static void addHeaderLine(Map> heads, StringBuilder line, + private static boolean addHeaderLine(Map> heads, StringBuilder line, int maxHeadersCount, int maxHeaderLength) throws IOException { // null lines are a nop final int size = line.length(); if (size == 0) { - return; + return false; } int separator = line.indexOf(":"); final String name; @@ -185,7 +194,7 @@ private static void addHeaderLine(Map> heads, StringBuilder LOG.fine("The attachment header size has exceeded the configured parameter: " + maxHeaderLength); throw new HeaderSizeExceededException(); } - v.add(value); + return 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 45cc5642616..3589eac71d8 100644 --- a/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java +++ b/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java @@ -742,6 +742,32 @@ public void testAttachmentHeaderSize() throws Exception { () -> ad.initializeAttachments()); } + @Test + public void testManyAttachmentRepeatedHeaders() throws Exception { + StringBuilder sb = new StringBuilder(10000); + // Add many attachment headers + sb.append("------=_Part_34950_1098328613.1263781527359\n"); + IntStream.range(0, 100).forEach(i -> sb.append("Header1").append(": ").append(i).append('\n')); + IntStream.range(0, 100).forEach(i -> sb.append("Header2").append(": ").append(i).append('\n')); + IntStream.range(0, 100).forEach(i -> sb.append("Header3").append(": ").append(i).append('\n')); + IntStream.range(0, 100).forEach(i -> sb.append("Header4").append(": ").append(i).append('\n')); + IntStream.range(0, 100).forEach(i -> sb.append("Header5").append(": ").append(i).append('\n')); + IntStream.range(0, 100).forEach(i -> sb.append("Header6").append(": ").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("\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 testAttachmentRepeatedHeaderSize() throws Exception { final Random random = new Random();