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


The following commit(s) were added to refs/heads/3.6.x-fixes by this push:
     new 658ad9101ff Make sure LazyAttachmentCollection respects max attachment 
count in all cases (#3344)
658ad9101ff is described below

commit 658ad9101ff0016f96fd9e424f0017789d9dc404
Author: Andriy Redko <[email protected]>
AuthorDate: Tue Jul 28 15:54:59 2026 -0400

    Make sure LazyAttachmentCollection respects max attachment count in all 
cases (#3344)
    
    (cherry picked from commit e18116b94588013b236791abfadd995122fb42c8)
---
 .../cxf/attachment/LazyAttachmentCollection.java   |  16 ++-
 .../cxf/attachment/AttachmentDeserializerTest.java | 124 +++++++++++++++++----
 .../apache/cxf/systest/jaxb/MTOMBase64Test.java    |   2 +
 3 files changed, 118 insertions(+), 24 deletions(-)

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 8dd4ace35c9..d1685ffb7c1 100644
--- a/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
+++ b/core/src/main/java/org/apache/cxf/attachment/LazyAttachmentCollection.java
@@ -74,6 +74,10 @@ public class LazyAttachmentCollection
      */
     public boolean hasNext(boolean shouldLoadNew) throws IOException {
         if (shouldLoadNew) {
+            if (attachments.size() > maxAttachmentCount) {
+                throw new IOException("The message contains more attachments 
than are permitted");
+            }
+
             Attachment a = deserializer.readNext();
             if (a != null) {
                 attachments.add(a);
@@ -88,6 +92,7 @@ public class LazyAttachmentCollection
         return hasNext(true);
     }
     public Iterator<Attachment> iterator() {
+        // CHECKSTYLE:OFF
         return new Iterator<Attachment>() {
             int current;
             boolean removed;
@@ -99,6 +104,9 @@ public class LazyAttachmentCollection
 
                 // check if there is another attachment
                 try {
+                    if (attachments.size() > maxAttachmentCount) {
+                        throw new IOException("The message contains more 
attachments than are permitted");
+                    }
                     Attachment a = deserializer.readNext();
                     if (a == null) {
                         return false;
@@ -126,8 +134,8 @@ public class LazyAttachmentCollection
                 attachments.remove(--current);
                 removed = true;
             }
-
         };
+        // CHECKSTYLE:ON
     }
 
     public int size() {
@@ -137,10 +145,16 @@ public class LazyAttachmentCollection
     }
 
     public boolean add(Attachment arg0) {
+        if (attachments.size() > maxAttachmentCount) {
+            throw new RuntimeException(new IOException("The message contains 
more attachments than are permitted"));
+        }
         return attachments.add(arg0);
     }
 
     public boolean addAll(Collection<? extends Attachment> arg0) {
+        if (attachments.size() + arg0.size() > maxAttachmentCount) {
+            throw new RuntimeException(new IOException("The message contains 
more attachments than are permitted"));
+        }
         return attachments.addAll(arg0);
     }
 
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 0027569dcc5..c5e8b145312 100644
--- 
a/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
+++ 
b/core/src/test/java/org/apache/cxf/attachment/AttachmentDeserializerTest.java
@@ -29,12 +29,14 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
 
+import javax.activation.DataHandler;
 import javax.activation.DataSource;
 import javax.activation.URLDataSource;
 import javax.xml.parsers.SAXParser;
@@ -711,33 +713,29 @@ public class AttachmentDeserializerTest {
         assertThrows("Failure expected on too many attachment headers", 
IOException.class, 
             () -> ad.initializeAttachments());
     }
-
     
     @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");
+    public void testManyAttachmentsDataHandlerIterator() throws Exception {
+        prepareAttachments();
 
-        // 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");
-        });
+        AttachmentDeserializer ad = new AttachmentDeserializer(msg);
+        ad.initializeAttachments();
+
+        // Force it to load the attachments
+        final LazyAttachmentCollection attachments = 
(LazyAttachmentCollection) msg.getAttachments();
+        assertThrows("Failure expected on too many attachments", 
RuntimeException.class, 
+            () -> {
+                // Exercise iterator() path
+                for (Map.Entry<String, DataHandler> entry : 
attachments.createDataHandlerMap().entrySet()) {
+                    // Do nothing, just force loading
+                }
+            });
+    }
+
+    @Test
+    public void testManyAttachmentsLoadAll() throws Exception {
+        prepareAttachments();
 
-        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();
 
@@ -746,6 +744,60 @@ public class AttachmentDeserializerTest {
             () -> msg.getAttachments().size());
     }
 
+    @Test
+    public void testManyAttachmentsIterator() throws Exception {
+        prepareAttachments();
+
+        AttachmentDeserializer ad = new AttachmentDeserializer(msg);
+        ad.initializeAttachments();
+
+        // Iterate over attachments
+        assertThrows("Failure expected on too many attachments", 
RuntimeException.class, 
+            () -> {
+                // Exercise iterator() path
+                for (Attachment attachment : msg.getAttachments()) {
+                    // Do nothing, just force loading
+                }
+            }
+        );
+        
+        // Iterate over attachments
+        final LazyAttachmentCollection attachments = 
(LazyAttachmentCollection) msg.getAttachments();
+        assertThrows("Failure expected on too many attachments", 
IOException.class, 
+            () -> {
+                // Exercise iterator() path
+                while (attachments.hasNext()) {
+                    // Do nothing, just force loading
+                }
+            }
+        );
+
+        assertThrows("Failure expected on too many attachments", 
RuntimeException.class, 
+            () -> attachments.add(new AttachmentImpl("contentId")));
+
+        assertThrows("Failure expected on too many attachments", 
RuntimeException.class, 
+            () -> attachments.addAll(List.of(new 
AttachmentImpl("contentId"))));
+    }
+
+    @Test
+    public void testManyAttachmentsHasNext() throws Exception {
+        prepareAttachments();
+
+        AttachmentDeserializer ad = new AttachmentDeserializer(msg);
+        ad.initializeAttachments();
+
+        // Iterate over attachments
+        final LazyAttachmentCollection attachments = 
(LazyAttachmentCollection) msg.getAttachments();
+        assertThrows("Failure expected on too many attachments", 
IOException.class, 
+            () -> {
+                // Exercise iterator() path
+                while (attachments.hasNext()) {
+                    // Do nothing, just force loading
+                }
+            }
+        );
+    }
+
     @Test
     public void testChangingMaxAttachmentCount() throws Exception {
         StringBuilder sb = new StringBuilder(1000);
@@ -954,4 +1006,30 @@ public class AttachmentDeserializerTest {
             
System.clearProperty(AttachmentUtil.ATTACHMENT_XOP_FOLLOW_URLS_PROPERTY);
         }
     }
+
+    private void prepareAttachments() {
+        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");
+    }
 }
diff --git 
a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/MTOMBase64Test.java
 
b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/MTOMBase64Test.java
index 7070b05dfa5..4e7490bf263 100644
--- 
a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/MTOMBase64Test.java
+++ 
b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/MTOMBase64Test.java
@@ -30,6 +30,7 @@ import javax.xml.ws.Service;
 import javax.xml.ws.soap.MTOM;
 import javax.xml.ws.soap.SOAPBinding;
 
+import org.apache.cxf.attachment.AttachmentDeserializer;
 import org.apache.cxf.ext.logging.Logging;
 import org.apache.cxf.ext.logging.LoggingInInterceptor;
 import org.apache.cxf.ext.logging.LoggingOutInterceptor;
@@ -111,6 +112,7 @@ public class MTOMBase64Test extends 
AbstractBusClientServerTestBase {
         protected void run() {
             EndpointImpl endpointImpl = 
(EndpointImpl)Endpoint.publish(ADDRESS, new MTOMServer());
             
endpointImpl.getProperties().put(Message.CONTENT_TRANSFER_ENCODING, "base64");
+            
endpointImpl.getBus().getProperties().put(AttachmentDeserializer.ATTACHMENT_MAX_COUNT,
 "100");
         }
         public static void main(String[] args) {
             try {

Reply via email to