Skip to content

Commit 35ffb9b

Browse files
authored
Merge pull request #1547 from cshannon/AMQ-9810-2
AMQ-9810 - Add additional validation for MQTT wireformat
2 parents 1a4660e + d0df9e2 commit 35ffb9b

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTCodec.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
public class MQTTCodec {
2727

28-
private static final int MAX_MULTIPLIER = (int) Math.pow(2, 21);
28+
static final int MAX_MULTIPLIER = (int) Math.pow(2, 21);
2929

3030
private final MQTTFrameSink frameSink;
3131
private final MQTTWireFormat wireFormat;

activemq-mqtt/src/main/java/org/apache/activemq/transport/mqtt/MQTTWireFormat.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import org.fusesource.hawtbuf.Buffer;
3030
import org.fusesource.mqtt.codec.MQTTFrame;
3131

32+
import static org.apache.activemq.transport.mqtt.MQTTCodec.MAX_MULTIPLIER;
33+
3234
/**
3335
* Implements marshalling and unmarsalling the <a
3436
* href="http://mqtt.org/">MQTT</a> protocol.
@@ -92,6 +94,10 @@ public Object unmarshal(DataInput dataIn) throws IOException {
9294
digit = dataIn.readByte();
9395
length += (digit & 0x7F) * multiplier;
9496
multiplier <<= 7;
97+
// MQTT protocol limits Remaining Length to 4 bytes
98+
if (multiplier == MAX_MULTIPLIER && (digit & 128) != 0) {
99+
throw new IOException("Remaining length exceeds 4 bytes");
100+
}
95101
}
96102
while ((digit & 0x80) != 0);
97103

activemq-mqtt/src/test/java/org/apache/activemq/transport/mqtt/MQTTCodecTest.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.List;
2828
import java.util.concurrent.TimeUnit;
2929

30+
import org.apache.activemq.util.ByteSequence;
3031
import org.fusesource.hawtbuf.Buffer;
3132
import org.fusesource.hawtbuf.DataByteArrayInputStream;
3233
import org.fusesource.hawtbuf.DataByteArrayOutputStream;
@@ -316,7 +317,6 @@ public void testMessageDecodingPerformance() throws Exception {
316317
LOG.info("Total time to process: {}", TimeUnit.MILLISECONDS.toSeconds(duration));
317318
}
318319

319-
320320
@Test
321321
public void testParseInvalidRemainingLengthField() throws Exception {
322322
try {
@@ -330,6 +330,7 @@ public void testParseInvalidRemainingLengthField() throws Exception {
330330
fail("Parsing should have failed invalid remaining length field");
331331
} catch (IOException e) {
332332
// expected
333+
assertEquals("Remaining length exceeds 4 bytes", e.getMessage());
333334
}
334335
}
335336

@@ -344,6 +345,20 @@ public void testPartialReadInvalidRemainingLengthField() throws Exception {
344345
fail("Parsing should have failed invalid remaining length field");
345346
} catch (IOException e) {
346347
// expected
348+
assertEquals("Remaining length exceeds 4 bytes", e.getMessage());
349+
}
350+
}
351+
352+
@Test
353+
public void testUnmarshalInvalidRemainingLengthField() {
354+
try {
355+
// Test Invalid remaining field checking using the marshaller
356+
wireFormat.unmarshal(new ByteSequence(new byte[]{CONNECT.TYPE, (byte) 0x81, (byte) 0x81,
357+
(byte) 0x81, (byte) 0x81}));
358+
fail("Parsing should have failed invalid remaining length field");
359+
} catch (IOException e) {
360+
// expected
361+
assertEquals("Remaining length exceeds 4 bytes", e.getMessage());
347362
}
348363
}
349364

0 commit comments

Comments
 (0)