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

coheigea pushed a commit to branch 3.2.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 44473b051ea3b0ea11666070f50c16f018d9fa7d
Author: Colm O hEigeartaigh <cohei...@apache.org>
AuthorDate: Tue Sep 3 15:45:20 2019 +0100

    Restrict the number of message attachments
    
    (cherry picked from commit 6c3990144b56097502aa9f3ec9c06f3031109022)
    (cherry picked from commit fd85803a73ad46f36816bcb55ed1c4f4b4c4312d)
    
    # Conflicts:
    #   
core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
---
 .../cxf/attachment/AttachmentDeserializer.java     |  17 ++-
 .../cxf/attachment/LazyAttachmentCollection.java   |   9 +-
 .../cxf/attachment/AttachmentDeserializerTest.java | 116 +++++++++++++++++----
 3 files changed, 121 insertions(+), 21 deletions(-)

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 7f46ec5..784bc3e 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentDeserializer.java
@@ -54,6 +54,11 @@ public class AttachmentDeserializer {
     public static final String ATTACHMENT_MAX_SIZE = "attachment-max-size";
 
     /**
+     * The maximum number of attachments permitted in a message. The default 
is 50.
+     */
+    public static final String ATTACHMENT_MAX_COUNT = "attachment-max-count";
+
+    /**
      * The maximum MIME Header Length. The default is 300.
      */
     public static final String ATTACHMENT_MAX_HEADER_SIZE = 
"attachment-max-header-size";
@@ -109,7 +114,17 @@ public class AttachmentDeserializer {
     public void initializeAttachments() throws IOException {
         initializeRootMessage();
 
-        attachments = new LazyAttachmentCollection(this);
+        Object maxCountProperty = 
message.getContextualProperty(AttachmentDeserializer.ATTACHMENT_MAX_COUNT);
+        int maxCount = 50;
+        if (maxCountProperty != null) {
+            if (maxCountProperty instanceof Integer) {
+                maxCount = (Integer)maxCountProperty;
+            } else {
+                maxCount = Integer.parseInt((String)maxCountProperty);
+            }
+        }
+
+        attachments = new LazyAttachmentCollection(this, maxCount);
         message.setAttachments(attachments);
     }
 
diff --git 
a/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java 
b/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
index c44ea21..d866029 100644
--- a/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
+++ b/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
@@ -37,10 +37,12 @@ public class LazyAttachmentCollection
 
     private AttachmentDeserializer deserializer;
     private final List<Attachment> attachments = new ArrayList<>();
+    private final int maxAttachmentCount;
 
-    public LazyAttachmentCollection(AttachmentDeserializer deserializer) {
+    public LazyAttachmentCollection(AttachmentDeserializer deserializer, int 
maxAttachmentCount) {
         super();
         this.deserializer = deserializer;
+        this.maxAttachmentCount = maxAttachmentCount;
     }
 
     public List<Attachment> getLoadedAttachments() {
@@ -50,8 +52,13 @@ public class LazyAttachmentCollection
     private void loadAll() {
         try {
             Attachment a = deserializer.readNext();
+            int count = 0;
             while (a != null) {
                 attachments.add(a);
+                count++;
+                if (count > maxAttachmentCount) {
+                    throw new IOException("The message contains more 
attachments than are permitted");
+                }
                 a = deserializer.readNext();
             }
         } catch (IOException e) {
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 51eb3b5..871ce3c 100644
--- 
a/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
+++ 
b/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
@@ -20,7 +20,6 @@ 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;
@@ -31,6 +30,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.IntStream;
 
 import javax.activation.DataSource;
 import javax.xml.parsers.SAXParser;
@@ -50,7 +50,13 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-public class AttachmentDeserializerTest extends Assert {
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class AttachmentDeserializerTest {
 
     private MessageImpl msg;
 
@@ -465,32 +471,17 @@ public class AttachmentDeserializerTest extends Assert {
 
         ad.initializeAttachments();
 
-        String s = getString(message.getContent(InputStream.class));
+        String s = IOUtils.toString(message.getContent(InputStream.class));
         assertEquals("JJJJ", s.trim());
         int count = 1;
         for (Attachment a : message.getAttachments()) {
-            s = getString(a.getDataHandler().getInputStream());
+            s = IOUtils.toString(a.getDataHandler().getInputStream());
             assertEquals("ABCD" + count++, s);
         }
 
         in.close();
     }
 
-    private String getString(InputStream ins) throws Exception {
-        try (ByteArrayOutputStream bout = new ByteArrayOutputStream(100)) {
-            byte b[] = new byte[100];
-            int i = ins.read(b);
-            while (i > 0) {
-                bout.write(b, 0, i);
-                i = ins.read(b);
-            }
-            if (i == 0) {
-                throw new IOException("Should not be 0");
-            }
-            return bout.toString();
-        }
-    }
-
     @Test
     public void testCXF3383() throws Exception {
         String contentType = "multipart/related; type=\"application/xop+xml\";"
@@ -676,5 +667,92 @@ public class AttachmentDeserializerTest extends Assert {
         assertEquals(-1, ins.read(new byte[1000], 100, 600));
         ins.close();
     }
+
+    @Test
+    public void testManyAttachments() throws Exception {
+        StringBuilder sb = new StringBuilder(1000);
+        sb.append("SomeHeader: foo\n")
+            .append("------=_Part_34950_1098328613.1263781527359\n")
+            .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");
+
+        // Add many attachments
+        IntStream.range(0, 100000).forEach(i -> {
+            sb.append("------=_Part_34950_1098328613.1263781527359\n")
+                .append("Content-Type: text/xml\n")
+                .append("Content-Transfer-Encoding: binary\n")
+                .append("Content-Id: <b86a5f2d-e7af-4e5e-b71a-9f6f2307cab0>\n")
+                .append('\n')
+                .append("<message>\n")
+                .append("------=_Part_34950_1098328613.1263781527359--\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);
+        ad.initializeAttachments();
+
+        // Force it to load the attachments
+        try {
+            msg.getAttachments().size();
+            fail("Failure expected on too many attachments");
+        } catch (RuntimeException ex) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testChangingMaxAttachmentCount() throws Exception {
+        StringBuilder sb = new StringBuilder(1000);
+        sb.append("SomeHeader: foo\n")
+            .append("------=_Part_34950_1098328613.1263781527359\n")
+            .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");
+
+        // Add many attachments
+        IntStream.range(0, 40).forEach(i -> {
+            sb.append("------=_Part_34950_1098328613.1263781527359\n")
+                .append("Content-Type: text/xml\n")
+                .append("Content-Transfer-Encoding: binary\n")
+                .append("Content-Id: <b86a5f2d-e7af-4e5e-b71a-9f6f2307cab0>\n")
+                .append('\n')
+                .append("<message>\n")
+                .append("------=_Part_34950_1098328613.1263781527359--\n");
+        });
+
+        msg = new MessageImpl();
+        msg.put(AttachmentDeserializer.ATTACHMENT_MAX_COUNT, "30");
+        msg.setContent(InputStream.class, new 
ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8)));
+        msg.put(Message.CONTENT_TYPE, "multipart/related");
+        AttachmentDeserializer ad = new AttachmentDeserializer(msg);
+        ad.initializeAttachments();
+
+        // Force it to load the attachments
+        try {
+            msg.getAttachments().size();
+            fail("Failure expected on too many attachments");
+        } catch (RuntimeException ex) {
+            // expected
+        }
+
+        // Now we'll allow it
+        msg = new MessageImpl();
+        msg.put(AttachmentDeserializer.ATTACHMENT_MAX_COUNT, "60");
+        msg.setContent(InputStream.class, new 
ByteArrayInputStream(sb.toString().getBytes(StandardCharsets.UTF_8)));
+        msg.put(Message.CONTENT_TYPE, "multipart/related");
+        ad = new AttachmentDeserializer(msg);
+        ad.initializeAttachments();
+
+        // Force it to load the attachments
+        assertEquals(40, msg.getAttachments().size());
+    }
+
 }
 

Reply via email to