From 8c12033261e097503851b30fbf6a8ce302e6f616 Mon Sep 17 00:00:00 2001 From: Matt Pavlovich Date: Mon, 8 Jul 2024 19:22:07 -0500 Subject: [PATCH] [AMQ-9519] Remove runtime usage of commons-io --- .../src/main/resources/features-core.xml | 1 - activemq-web/pom.xml | 4 -- .../activemq/web/MessageServletSupport.java | 59 +++++++++++++------ assembly/src/main/descriptors/common-bin.xml | 1 - 4 files changed, 42 insertions(+), 23 deletions(-) diff --git a/activemq-karaf/src/main/resources/features-core.xml b/activemq-karaf/src/main/resources/features-core.xml index 3f6bf85c871..1ebd87d510b 100644 --- a/activemq-karaf/src/main/resources/features-core.xml +++ b/activemq-karaf/src/main/resources/features-core.xml @@ -55,7 +55,6 @@ connector http activemq-client - mvn:commons-io/commons-io/${commons-io-version} mvn:org.apache.commons/commons-lang3/${commons-lang-version} mvn:commons-codec/commons-codec/1.15 mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.velocity/1.7_6 diff --git a/activemq-web/pom.xml b/activemq-web/pom.xml index cec0c079d55..43782fcde95 100644 --- a/activemq-web/pom.xml +++ b/activemq-web/pom.xml @@ -54,10 +54,6 @@ ${project.groupId} activemq-pool - - commons-io - commons-io - ${project.groupId} activemq-unit-tests diff --git a/activemq-web/src/main/java/org/apache/activemq/web/MessageServletSupport.java b/activemq-web/src/main/java/org/apache/activemq/web/MessageServletSupport.java index 3ff6351ff8c..8f1a7e9869b 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/MessageServletSupport.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/MessageServletSupport.java @@ -17,9 +17,9 @@ package org.apache.activemq.web; -import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -35,7 +35,6 @@ import org.apache.activemq.command.ActiveMQDestination; import org.apache.activemq.command.ActiveMQQueue; import org.apache.activemq.command.ActiveMQTopic; -import org.apache.commons.io.input.BoundedInputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -65,7 +64,7 @@ public abstract class MessageServletSupport extends HttpServlet { * is given by DEFAULT_MAX_MESSAGE_SIZE below. */ private static final String MAX_MESSAGE_SIZE_TAG = "maxMessageSize"; - private static final Long DEFAULT_MAX_MESSAGE_SIZE = 100000L; + private static final Long DEFAULT_MAX_MESSAGE_SIZE = 100_000L; private boolean defaultTopicFlag = true; private Destination defaultDestination; @@ -355,21 +354,43 @@ protected boolean isTopic(HttpServletRequest request) { protected String getPostedMessageBody(HttpServletRequest request) throws IOException { String answer = request.getParameter(bodyParameter); String contentType = request.getContentType(); - if (answer == null && contentType != null) { - LOG.debug("Content-Type={}", contentType); - // lets read the message body instead - BoundedInputStream boundedInputStream = new BoundedInputStream(request.getInputStream(), maxMessageSize); - BufferedReader reader = new BufferedReader(new InputStreamReader(boundedInputStream)); - StringBuilder buffer = new StringBuilder(); - while (true) { - String line = reader.readLine(); - if (line == null) { - break; + long contentLengthLong = request.getContentLengthLong(); + + if (answer == null && contentType != null && contentLengthLong > -1l) { + LOG.debug("Content-Type={} Content-Length={} maxMessageSize={}", contentType, contentLengthLong, maxMessageSize); + + if (contentLengthLong > maxMessageSize) { + LOG.warn("Message body exceeds max allowed size. Content-Type={} Content-Length={} maxMessageSize={}", contentType, contentLengthLong, maxMessageSize); + throw new IOException("Message body exceeds max allowed size"); + } + + if (contentLengthLong >= Long.valueOf(Integer.MAX_VALUE)) { + LOG.warn("Message body longer than {} is not supported", Integer.MAX_VALUE); + throw new IOException("Message body exceeds max supported size"); + } + + // This is safe b/c we bounds checked above + int expectedBodySize = (int) contentLengthLong; + try(ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(expectedBodySize)) { + byte[] buffer = new byte[2048]; + int length; + int totalRead = 0; + while ((length = request.getInputStream().read(buffer)) != -1) { + + if((Integer.MAX_VALUE - totalRead) < length) { + LOG.warn("Message body exceeds max allowed size. Content-Type={} Content-Length={} maxMessageSize={}", contentType, contentLengthLong, maxMessageSize); + throw new IOException("Message body exceeded expected size"); + } + + totalRead += length; + if(isMaxBodySizeExceeded(totalRead, expectedBodySize)) { + LOG.warn("Message body exceeds max allowed size. Content-Type={} Content-Length={} maxMessageSize={}", contentType, contentLengthLong, maxMessageSize); + throw new IOException("Message body exceeds max allowed size"); + } + byteArrayOutputStream.write(buffer, 0, length); } - buffer.append(line); - buffer.append("\n"); + return byteArrayOutputStream.toString(StandardCharsets.UTF_8); } - return buffer.toString(); } return answer; } @@ -377,4 +398,8 @@ protected String getPostedMessageBody(HttpServletRequest request) throws IOExcep protected String getSelector(HttpServletRequest request) throws IOException { return request.getHeader(WebClient.selectorName); } + + private boolean isMaxBodySizeExceeded(int totalRead, int expectedBodySize) { + return totalRead < 0 || totalRead >= Integer.MAX_VALUE || totalRead >= maxMessageSize || totalRead > expectedBodySize; + } } diff --git a/assembly/src/main/descriptors/common-bin.xml b/assembly/src/main/descriptors/common-bin.xml index e1287699615..81ea92c9673 100644 --- a/assembly/src/main/descriptors/common-bin.xml +++ b/assembly/src/main/descriptors/common-bin.xml @@ -204,7 +204,6 @@ ${pom.groupId}:activemq-shiro commons-beanutils:commons-beanutils commons-collections:commons-collections - commons-io:commons-io org.apache.commons:commons-dbcp2 org.apache.commons:commons-pool2 commons-codec:commons-codec