Skip to content

Commit 8664499

Browse files
fix: ensure the payload format is valid
This commit should prevent some NPE issues encountered after the parsing of the packet. Related: - #642 - #609 - #505 Backported from e8ffe9d
1 parent 8bd35da commit 8664499

File tree

6 files changed

+72
-42
lines changed

6 files changed

+72
-42
lines changed

Diff for: src/main/java/io/socket/client/Manager.java

+9-12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.socket.backo.Backoff;
44
import io.socket.emitter.Emitter;
5+
import io.socket.parser.DecodingException;
56
import io.socket.parser.IOParser;
67
import io.socket.parser.Packet;
78
import io.socket.parser.Parser;
@@ -370,10 +371,14 @@ private void onopen() {
370371
@Override
371372
public void call(Object... objects) {
372373
Object data = objects[0];
373-
if (data instanceof String) {
374-
Manager.this.ondata((String)data);
375-
} else if (data instanceof byte[]) {
376-
Manager.this.ondata((byte[])data);
374+
try {
375+
if (data instanceof String) {
376+
Manager.this.decoder.add((String) data);
377+
} else if (data instanceof byte[]) {
378+
Manager.this.decoder.add((byte[]) data);
379+
}
380+
} catch (DecodingException e) {
381+
logger.fine("error while decoding the packet: " + e.getMessage());
377382
}
378383
}
379384
}));
@@ -419,14 +424,6 @@ private void onpong() {
419424
null != this.lastPing ? new Date().getTime() - this.lastPing.getTime() : 0);
420425
}
421426

422-
private void ondata(String data) {
423-
this.decoder.add(data);
424-
}
425-
426-
private void ondata(byte[] data) {
427-
this.decoder.add(data);
428-
}
429-
430427
private void ondecoded(Packet packet) {
431428
this.emit(EVENT_PACKET, packet);
432429
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package io.socket.parser;
2+
3+
public class DecodingException extends RuntimeException {
4+
public DecodingException(String message) {
5+
super(message);
6+
}
7+
}

Diff for: src/main/java/io/socket/parser/IOParser.java

+35-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package io.socket.parser;
22

33
import io.socket.hasbinary.HasBinary;
4+
import org.json.JSONArray;
45
import org.json.JSONException;
6+
import org.json.JSONObject;
57
import org.json.JSONTokener;
68

79
import java.util.ArrayList;
@@ -14,10 +16,6 @@ final public class IOParser implements Parser {
1416

1517
private static final Logger logger = Logger.getLogger(IOParser.class.getName());
1618

17-
private static Packet<String> error() {
18-
return new Packet<String>(ERROR, "parser error");
19-
}
20-
2119
private IOParser() {}
2220

2321
final public static class Encoder implements Parser.Encoder {
@@ -126,12 +124,16 @@ private static Packet decodeString(String str) {
126124
int i = 0;
127125
int length = str.length();
128126

129-
Packet<Object> p = new Packet<Object>(Character.getNumericValue(str.charAt(0)));
127+
Packet<Object> p = new Packet<>(Character.getNumericValue(str.charAt(0)));
130128

131-
if (p.type < 0 || p.type > types.length - 1) return error();
129+
if (p.type < 0 || p.type > types.length - 1) {
130+
throw new DecodingException("unknown packet type " + p.type);
131+
}
132132

133133
if (BINARY_EVENT == p.type || BINARY_ACK == p.type) {
134-
if (!str.contains("-") || length <= i + 1) return error();
134+
if (!str.contains("-") || length <= i + 1) {
135+
throw new DecodingException("illegal attachments");
136+
}
135137
StringBuilder attachments = new StringBuilder();
136138
while (str.charAt(++i) != '-') {
137139
attachments.append(str.charAt(i));
@@ -170,7 +172,7 @@ private static Packet decodeString(String str) {
170172
try {
171173
p.id = Integer.parseInt(id.toString());
172174
} catch (NumberFormatException e){
173-
return error();
175+
throw new DecodingException("invalid payload");
174176
}
175177
}
176178
}
@@ -181,7 +183,10 @@ private static Packet decodeString(String str) {
181183
p.data = new JSONTokener(str.substring(i)).nextValue();
182184
} catch (JSONException e) {
183185
logger.log(Level.WARNING, "An error occured while retrieving data from JSONTokener", e);
184-
return error();
186+
throw new DecodingException("invalid payload");
187+
}
188+
if (!isPayloadValid(p.type, p.data)) {
189+
throw new DecodingException("invalid payload");
185190
}
186191
}
187192

@@ -191,6 +196,27 @@ private static Packet decodeString(String str) {
191196
return p;
192197
}
193198

199+
private static boolean isPayloadValid(int type, Object payload) {
200+
switch (type) {
201+
case Parser.CONNECT:
202+
return payload instanceof JSONObject;
203+
case Parser.ERROR:
204+
return payload instanceof String;
205+
case Parser.DISCONNECT:
206+
return payload == null;
207+
case Parser.EVENT:
208+
case Parser.BINARY_EVENT:
209+
return payload instanceof JSONArray
210+
&& ((JSONArray) payload).length() > 0
211+
&& !((JSONArray) payload).isNull(0);
212+
case Parser.ACK:
213+
case Parser.BINARY_ACK:
214+
return payload instanceof JSONArray;
215+
default:
216+
return false;
217+
}
218+
}
219+
194220
@Override
195221
public void destroy() {
196222
if (this.reconstructor != null) {

Diff for: src/test/java/io/socket/parser/ByteArrayTest.java

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package io.socket.parser;
22

3-
import io.socket.emitter.Emitter;
43
import org.json.JSONArray;
54
import org.json.JSONException;
6-
import org.json.JSONObject;
75
import org.junit.Test;
86
import org.junit.runner.RunWith;
97
import org.junit.runners.JUnit4;
108

119
import java.nio.charset.Charset;
10+
import java.nio.charset.StandardCharsets;
1211

12+
import static java.util.Arrays.asList;
1313
import static org.hamcrest.CoreMatchers.is;
1414
import static org.junit.Assert.assertThat;
1515

@@ -20,29 +20,29 @@ public class ByteArrayTest {
2020

2121
@Test
2222
public void encodeByteArray() {
23-
Packet<byte[]> packet = new Packet<byte[]>(Parser.BINARY_EVENT);
24-
packet.data = "abc".getBytes(Charset.forName("UTF-8"));
23+
Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
24+
packet.data = new JSONArray(asList("abc", "abc".getBytes(StandardCharsets.UTF_8)));
2525
packet.id = 23;
2626
packet.nsp = "/cool";
2727
Helpers.testBin(packet);
2828
}
2929

3030
@Test
3131
public void encodeByteArray2() {
32-
Packet<byte[]> packet = new Packet<byte[]>(Parser.BINARY_EVENT);
33-
packet.data = new byte[2];
32+
Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
33+
packet.data = new JSONArray(asList("2", new byte[] { 0, 1 }));
3434
packet.id = 0;
3535
packet.nsp = "/";
3636
Helpers.testBin(packet);
3737
}
3838

3939
@Test
4040
public void encodeByteArrayDeepInJson() throws JSONException {
41-
JSONObject data = new JSONObject("{a: \"hi\", b: {}, c: {a: \"bye\", b: {}}}");
42-
data.getJSONObject("b").put("why", new byte[3]);
43-
data.getJSONObject("c").getJSONObject("b").put("a", new byte[6]);
41+
JSONArray data = new JSONArray("[{a: \"hi\", b: {}, c: {a: \"bye\", b: {}}}]");
42+
data.getJSONObject(0).getJSONObject("b").put("why", new byte[3]);
43+
data.getJSONObject(0).getJSONObject("c").getJSONObject("b").put("a", new byte[6]);
4444

45-
Packet<JSONObject> packet = new Packet<JSONObject>(Parser.BINARY_EVENT);
45+
Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
4646
packet.data = data;
4747
packet.id = 999;
4848
packet.nsp = "/deep";
@@ -51,10 +51,10 @@ public void encodeByteArrayDeepInJson() throws JSONException {
5151

5252
@Test
5353
public void encodeDeepBinaryJSONWithNullValue() throws JSONException {
54-
JSONObject data = new JSONObject("{a: \"b\", c: 4, e: {g: null}, h: null}");
55-
data.put("h", new byte[9]);
54+
JSONArray data = new JSONArray("[{a: \"b\", c: 4, e: {g: null}, h: null}]");
55+
data.getJSONObject(0).put("h", new byte[9]);
5656

57-
Packet<JSONObject> packet = new Packet<JSONObject>(Parser.BINARY_EVENT);
57+
Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
5858
packet.data = data;
5959
packet.nsp = "/";
6060
packet.id = 600;

Diff for: src/test/java/io/socket/parser/Helpers.java

+5-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.socket.parser;
22

3-
import io.socket.emitter.Emitter;
43
import org.json.JSONArray;
54
import org.json.JSONException;
65
import org.json.JSONObject;
@@ -10,6 +9,7 @@
109

1110
import static org.hamcrest.CoreMatchers.is;
1211
import static org.junit.Assert.assertThat;
12+
import static org.junit.Assert.fail;
1313

1414
@RunWith(JUnit4.class)
1515
public class Helpers {
@@ -35,13 +35,10 @@ public void call(Packet packet) {
3535

3636
public static void testDecodeError(final String errorMessage) {
3737
Parser.Decoder decoder = new IOParser.Decoder();
38-
decoder.onDecoded(new IOParser.Decoder.Callback() {
39-
@Override
40-
public void call(Packet packet) {
41-
assertPacket(errorPacket, packet);
42-
}
43-
});
44-
decoder.add(errorMessage);
38+
try {
39+
decoder.add(errorMessage);
40+
fail();
41+
} catch (DecodingException e) {}
4542
}
4643

4744
@SuppressWarnings("unchecked")

Diff for: src/test/java/io/socket/parser/ParserTest.java

+3
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,8 @@ public void decodeInError() throws JSONException {
6363
Helpers.testDecodeError(Parser.EVENT + "2sd");
6464
// event with invalid json data
6565
Helpers.testDecodeError(Parser.EVENT + "2[\"a\",1,{asdf}]");
66+
Helpers.testDecodeError(Parser.EVENT + "2{}");
67+
Helpers.testDecodeError(Parser.EVENT + "2[]");
68+
Helpers.testDecodeError(Parser.EVENT + "2[null]");
6669
}
6770
}

0 commit comments

Comments
 (0)