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

cshannon pushed a commit to branch activemq-6.1.x
in repository https://gitbox.apache.org/repos/asf/activemq.git


The following commit(s) were added to refs/heads/activemq-6.1.x by this push:
     new f6b062fff0 AMQ-9810 - Add additional validation for MQTT control 
packets
f6b062fff0 is described below

commit f6b062fff00df031a2766873a250a9f7f9ca9697
Author: Christopher L. Shannon <[email protected]>
AuthorDate: Fri Nov 21 14:33:27 2025 -0500

    AMQ-9810 - Add additional validation for MQTT control packets
    
    Validate that the remaining length field is the correct number of bytes
    
    (cherry picked from commit 165e80bad459054bb8e422d58c2d1b42ab90003b)
---
 .../apache/activemq/transport/mqtt/MQTTCodec.java  |  6 ++++
 .../activemq/transport/mqtt/MQTTCodecTest.java     | 33 ++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git 
a/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTCodec.java 
b/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTCodec.java
index 12c9981db2..06efe49910 100644
--- 
a/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTCodec.java
+++ 
b/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTCodec.java
@@ -25,6 +25,8 @@ import org.fusesource.mqtt.codec.MQTTFrame;
 
 public class MQTTCodec {
 
+    private static final int MAX_MULTIPLIER = (int) Math.pow(2, 21);
+
     private final MQTTFrameSink frameSink;
     private final MQTTWireFormat wireFormat;
 
@@ -159,6 +161,10 @@ public class MQTTCodec {
             int i = 0;
             while (i++ < readSize) {
                 digit = data.readByte();
+                // MQTT protocol limits Remaining Length to 4 bytes
+                if (multiplier == MAX_MULTIPLIER && (digit & 128) != 0) {
+                    throw new IOException("Remaining length exceeds 4 bytes");
+                }
                 length += (digit & 0x7F) * multiplier;
                 multiplier <<= 7;
                 if ((digit & 0x80) == 0) {
diff --git 
a/activemq-mqtt/src/test/java/org/apache/activemq/transport/mqtt/MQTTCodecTest.java
 
b/activemq-mqtt/src/test/java/org/apache/activemq/transport/mqtt/MQTTCodecTest.java
index 49722d8eec..b14fba8c58 100644
--- 
a/activemq-mqtt/src/test/java/org/apache/activemq/transport/mqtt/MQTTCodecTest.java
+++ 
b/activemq-mqtt/src/test/java/org/apache/activemq/transport/mqtt/MQTTCodecTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.io.IOException;
 import java.net.ProtocolException;
 import java.util.ArrayList;
 import java.util.List;
@@ -314,4 +315,36 @@ public class MQTTCodecTest {
 
         LOG.info("Total time to process: {}", 
TimeUnit.MILLISECONDS.toSeconds(duration));
     }
+
+
+    @Test
+    public void testParseInvalidRemainingLengthField() throws Exception {
+        try {
+            // The maximum bytes in the remaining length field is 4
+            // The most significant bit is used to indicate that there are 
following bytes in the representation.
+            // If the most significant digit is a 1 in byte 4 that is an error 
and invalid length field
+            final Buffer buffer = new Buffer(new byte[]{CONNECT.TYPE, (byte) 
0x81, (byte) 0x81,
+                    (byte) 0x81, (byte) 0x81});
+            final DataByteArrayInputStream input = new 
DataByteArrayInputStream(buffer);
+            codec.parse(input, buffer.length());
+            fail("Parsing should have failed invalid remaining length field");
+        } catch (IOException e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testPartialReadInvalidRemainingLengthField() throws Exception {
+        // Test Invalid remaining field checking still works with partial reads
+        Buffer buffer = new Buffer(new byte[]{CONNECT.TYPE, (byte) 0x81, 
(byte) 0x81});
+        codec.parse(new DataByteArrayInputStream(buffer), buffer.length());
+        try {
+            buffer = new Buffer(new byte[]{(byte) 0x81, (byte) 0x81});
+            codec.parse(new DataByteArrayInputStream(buffer), buffer.length());
+            fail("Parsing should have failed invalid remaining length field");
+        } catch (IOException e) {
+            // expected
+        }
+    }
+
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact


Reply via email to