Skip to content

Commit 240f82f

Browse files
author
Ranjan Dasgupta
authored
Merge pull request #819 from silh/fix-mqttv3-utf8-check
Fixed the check for surrogates in mqtt3.
2 parents 17fd7be + dd0e0bb commit 240f82f

2 files changed

Lines changed: 32 additions & 21 deletions

File tree

  • org.eclipse.paho.client.mqttv3.test/src/test/java/org/eclipse/paho/client/mqttv3/test
  • org.eclipse.paho.client.mqttv3/src/main/java/org/eclipse/paho/client/mqttv3/internal/wire

org.eclipse.paho.client.mqttv3.test/src/test/java/org/eclipse/paho/client/mqttv3/test/MqttDataTypesTest.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.eclipse.paho.client.mqttv3.test;
22

33
import java.io.*;
4-
import java.nio.charset.Charset;
54
import java.nio.charset.StandardCharsets;
65

76
import org.eclipse.paho.client.mqttv3.MqttException;
@@ -72,6 +71,25 @@ public void TestEncodeInvalidUTF8StringInDifferentRange() throws MqttException {
7271
encodeAndDecodeString(invalidString);
7372
}
7473

74+
@Test
75+
public void TestEncodeAndDecodeUTF8StringWithSurrogates() throws MqttException {
76+
String testString = "\uD801\uDC37";
77+
String decodedUTF8 = encodeAndDecodeString(testString);
78+
Assert.assertEquals(testString, decodedUTF8);
79+
}
80+
81+
@Test(expected = IllegalArgumentException.class)
82+
public void TestEncodeAndDecodeUTF8StringWithTrailingHighSurrogate() throws MqttException {
83+
String testString = "\uD801";
84+
encodeAndDecodeString(testString);
85+
}
86+
87+
@Test(expected = IllegalArgumentException.class)
88+
public void TestEncodeAndDecodeUTF8StringWithLowSurrogate() throws MqttException {
89+
String testString = "\uDC37";
90+
encodeAndDecodeString(testString);
91+
}
92+
7593
@Test
7694
public void TestEncodeAndDecodeUTF8String() throws MqttException {
7795
String testString = "Answer to life the universe and everything";
@@ -91,14 +109,11 @@ public void TestEncodeAndDecodeChineseUTF8String() throws MqttException {
91109

92110
}
93111

94-
@Test(expected = IllegalArgumentException.class)
112+
@Test
95113
public void TestEncodeAndDecodeEmojiString() throws MqttException {
96114
String testString = "👁🐝Ⓜ️️";
97-
// System.out.println(String.format("'%s' is %d bytes, %d chars long",
98-
// testString, testString.getBytes().length, testString.length()));
99115
String decodedUTF8 = encodeAndDecodeString(testString);
100116
Assert.assertEquals(testString, decodedUTF8);
101-
102117
}
103118

104119
@Test

org.eclipse.paho.client.mqttv3/src/main/java/org/eclipse/paho/client/mqttv3/internal/wire/MqttWireMessage.java

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public abstract class MqttWireMessage {
5454
private static final String[] PACKET_NAMES = {"reserved", "CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC",
5555
"PUBREL", "PUBCOMP", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP",
5656
"DISCONNECT"};
57-
57+
5858

5959
private static final long FOUR_BYTE_INT_MAX = 4294967295L;
6060
private static final int VARIABLE_BYTE_INT_MAX = 268435455;
@@ -375,44 +375,40 @@ public static String decodeUTF8(DataInputStream input) throws MqttException {
375375
*
376376
* @param input
377377
* - The Input String
378-
* @throws IllegalArgumentException
378+
* @throws IllegalArgumentException - thrown if input String contains illegal characters or character sequences.
379379
*/
380380
private static void validateUTF8String(String input) throws IllegalArgumentException {
381381
for (int i = 0; i < input.length(); i++) {
382382
boolean isBad = false;
383383
char c = input.charAt(i);
384-
/* Check for mismatched surrogates */
384+
// Check for mismatched surrogates
385385
if (Character.isHighSurrogate(c)) {
386386
if (++i == input.length()) {
387387
isBad = true; /* Trailing high surrogate */
388388
} else {
389389
char c2 = input.charAt(i);
390390
if (Character.isLowSurrogate(c2)) {
391-
isBad = true; /* No low surrogate */
392-
} else {
393391
int ch = ((((int) c) & 0x3ff) << 10) | (c2 & 0x3ff);
394392
if ((ch & 0xffff) == 0xffff || (ch & 0xffff) == 0xfffe) {
395393
isBad = true; /* Noncharacter in base plane */
396394
}
395+
} else {
396+
isBad = true; /* No low surrogate */
397397
}
398398
}
399-
} else {
400-
if (Character.isISOControl(c) || Character.isLowSurrogate(c)) {
401-
isBad = true; /* Control character or no high surrogate */
402-
} else if (c >= 0xfdd0 && (c == 0xfffe || c >= 0xfdd0 || c <= 0xfddf)) {
403-
isBad = true; /* Noncharacter in other nonbase plane */
404-
}
399+
} else if (Character.isISOControl(c) // Control character
400+
|| Character.isLowSurrogate(c) // or no high surrogate
401+
|| c >= 0xfdd0 && (c <= 0xfddf || c >= 0xfffe)) { // non-character in other nonbase plane
402+
isBad = true;
405403
}
406404
if (isBad) {
407-
throw new IllegalArgumentException(String.format("Invalid UTF-8 char: [%x]", (int) c));
405+
throw new IllegalArgumentException(String.format("Invalid UTF-8 char: [%04x]", (int) c));
408406
}
409407
}
410408
}
411-
409+
412410
public static void validateVariableByteInt(int value) throws IllegalArgumentException {
413-
if (value >= 0 && value <= VARIABLE_BYTE_INT_MAX) {
414-
return;
415-
} else {
411+
if (value < 0 || value > VARIABLE_BYTE_INT_MAX) {
416412
throw new IllegalArgumentException("This property must be a number between 0 and " + VARIABLE_BYTE_INT_MAX);
417413
}
418414

0 commit comments

Comments
 (0)