This is an automated email from the ASF dual-hosted git repository. jbonofre pushed a commit to branch activemq-5.18.x in repository https://gitbox.apache.org/repos/asf/activemq.git
commit a2568aefd4a45a56e090a236c20fe7ad4e7a694a Author: Christopher L. Shannon <[email protected]> AuthorDate: Fri Nov 21 17:53:36 2025 -0500 AMQ-9810 - Add additional validation for MQTT wireformat Validate that the remaining length field is the correct number of bytes in MQTTWireFormat --- .../org/apache/activemq/transport/mqtt/MQTTCodec.java | 2 +- .../apache/activemq/transport/mqtt/MQTTWireFormat.java | 6 ++++++ .../apache/activemq/transport/mqtt/MQTTCodecTest.java | 17 ++++++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) 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 06efe49910..66a0ae5eb0 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,7 +25,7 @@ import org.fusesource.mqtt.codec.MQTTFrame; public class MQTTCodec { - private static final int MAX_MULTIPLIER = (int) Math.pow(2, 21); + static final int MAX_MULTIPLIER = (int) Math.pow(2, 21); private final MQTTFrameSink frameSink; private final MQTTWireFormat wireFormat; diff --git a/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTWireFormat.java b/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTWireFormat.java index 382247f018..9e79fd25f4 100644 --- a/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTWireFormat.java +++ b/activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTWireFormat.java @@ -29,6 +29,8 @@ import org.apache.activemq.wireformat.WireFormat; import org.fusesource.hawtbuf.Buffer; import org.fusesource.mqtt.codec.MQTTFrame; +import static org.apache.activemq.transport.mqtt.MQTTCodec.MAX_MULTIPLIER; + /** * Implements marshalling and unmarsalling the <a * href="http://mqtt.org/">MQTT</a> protocol. @@ -92,6 +94,10 @@ public class MQTTWireFormat implements WireFormat { digit = dataIn.readByte(); length += (digit & 0x7F) * multiplier; multiplier <<= 7; + // MQTT protocol limits Remaining Length to 4 bytes + if (multiplier == MAX_MULTIPLIER && (digit & 128) != 0) { + throw new IOException("Remaining length exceeds 4 bytes"); + } } while ((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 b14fba8c58..994bff4e67 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 @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; +import org.apache.activemq.util.ByteSequence; import org.fusesource.hawtbuf.Buffer; import org.fusesource.hawtbuf.DataByteArrayInputStream; import org.fusesource.hawtbuf.DataByteArrayOutputStream; @@ -316,7 +317,6 @@ public class MQTTCodecTest { LOG.info("Total time to process: {}", TimeUnit.MILLISECONDS.toSeconds(duration)); } - @Test public void testParseInvalidRemainingLengthField() throws Exception { try { @@ -330,6 +330,7 @@ public class MQTTCodecTest { fail("Parsing should have failed invalid remaining length field"); } catch (IOException e) { // expected + assertEquals("Remaining length exceeds 4 bytes", e.getMessage()); } } @@ -344,6 +345,20 @@ public class MQTTCodecTest { fail("Parsing should have failed invalid remaining length field"); } catch (IOException e) { // expected + assertEquals("Remaining length exceeds 4 bytes", e.getMessage()); + } + } + + @Test + public void testUnmarshalInvalidRemainingLengthField() { + try { + // Test Invalid remaining field checking using the marshaller + wireFormat.unmarshal(new ByteSequence(new byte[]{CONNECT.TYPE, (byte) 0x81, (byte) 0x81, + (byte) 0x81, (byte) 0x81})); + fail("Parsing should have failed invalid remaining length field"); + } catch (IOException e) { + // expected + assertEquals("Remaining length exceeds 4 bytes", e.getMessage()); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected] For further information, visit: https://activemq.apache.org/contact
