fix: ensure the payload format is valid

This commit should prevent some NPE issues encountered after the
parsing of the packet.

Related:

- https://github.com/socketio/socket.io-client-java/issues/642
- https://github.com/socketio/socket.io-client-java/issues/609
- https://github.com/socketio/socket.io-client-java/issues/505
This commit is contained in:
Damien Arrachequesne
2021-04-26 23:30:53 +02:00
parent 4885e7d59f
commit e8ffe9d138
4 changed files with 50 additions and 34 deletions

View File

@@ -326,10 +326,14 @@ public class Manager extends Emitter {
@Override @Override
public void call(Object... objects) { public void call(Object... objects) {
Object data = objects[0]; Object data = objects[0];
try {
if (data instanceof String) { if (data instanceof String) {
Manager.this.ondata((String)data); Manager.this.decoder.add((String) data);
} else if (data instanceof byte[]) { } else if (data instanceof byte[]) {
Manager.this.ondata((byte[])data); Manager.this.decoder.add((byte[]) data);
}
} catch (DecodingException e) {
logger.fine("error while decoding the packet: " + e.getMessage());
} }
} }
})); }));
@@ -353,22 +357,6 @@ public class Manager extends Emitter {
}); });
} }
private void ondata(String data) {
try {
this.decoder.add(data);
} catch (DecodingException e) {
this.onerror(e);
}
}
private void ondata(byte[] data) {
try {
this.decoder.add(data);
} catch (DecodingException e) {
this.onerror(e);
}
}
private void ondecoded(Packet packet) { private void ondecoded(Packet packet) {
this.emit(EVENT_PACKET, packet); this.emit(EVENT_PACKET, packet);
} }

View File

@@ -1,7 +1,9 @@
package io.socket.parser; package io.socket.parser;
import io.socket.hasbinary.HasBinary; import io.socket.hasbinary.HasBinary;
import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener; import org.json.JSONTokener;
import java.util.ArrayList; import java.util.ArrayList;
@@ -183,6 +185,9 @@ final public class IOParser implements Parser {
logger.log(Level.WARNING, "An error occured while retrieving data from JSONTokener", e); logger.log(Level.WARNING, "An error occured while retrieving data from JSONTokener", e);
throw new DecodingException("invalid payload"); throw new DecodingException("invalid payload");
} }
if (!isPayloadValid(p.type, p.data)) {
throw new DecodingException("invalid payload");
}
} }
if (logger.isLoggable(Level.FINE)) { if (logger.isLoggable(Level.FINE)) {
@@ -191,6 +196,26 @@ final public class IOParser implements Parser {
return p; return p;
} }
private static boolean isPayloadValid(int type, Object payload) {
switch (type) {
case Parser.CONNECT:
case Parser.CONNECT_ERROR:
return payload instanceof JSONObject;
case Parser.DISCONNECT:
return payload == null;
case Parser.EVENT:
case Parser.BINARY_EVENT:
return payload instanceof JSONArray
&& ((JSONArray) payload).length() > 0
&& !((JSONArray) payload).isNull(0);
case Parser.ACK:
case Parser.BINARY_ACK:
return payload instanceof JSONArray;
default:
return false;
}
}
@Override @Override
public void destroy() { public void destroy() {
if (this.reconstructor != null) { if (this.reconstructor != null) {

View File

@@ -1,15 +1,15 @@
package io.socket.parser; package io.socket.parser;
import io.socket.emitter.Emitter;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.JUnit4; import org.junit.runners.JUnit4;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static java.util.Arrays.asList;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
@@ -19,9 +19,9 @@ public class ByteArrayTest {
private static Parser.Encoder encoder = new IOParser.Encoder(); private static Parser.Encoder encoder = new IOParser.Encoder();
@Test @Test
public void encodeByteArray() { public void encodeByteArray() throws JSONException {
Packet<byte[]> packet = new Packet<>(Parser.BINARY_EVENT); Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
packet.data = "abc".getBytes(Charset.forName("UTF-8")); packet.data = new JSONArray(asList("abc", "abc".getBytes(StandardCharsets.UTF_8)));
packet.id = 23; packet.id = 23;
packet.nsp = "/cool"; packet.nsp = "/cool";
Helpers.testBin(packet); Helpers.testBin(packet);
@@ -29,8 +29,8 @@ public class ByteArrayTest {
@Test @Test
public void encodeByteArray2() { public void encodeByteArray2() {
Packet<byte[]> packet = new Packet<>(Parser.BINARY_EVENT); Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
packet.data = new byte[2]; packet.data = new JSONArray(asList("2", new byte[] { 0, 1 }));
packet.id = 0; packet.id = 0;
packet.nsp = "/"; packet.nsp = "/";
Helpers.testBin(packet); Helpers.testBin(packet);
@@ -38,11 +38,11 @@ public class ByteArrayTest {
@Test @Test
public void encodeByteArrayDeepInJson() throws JSONException { public void encodeByteArrayDeepInJson() throws JSONException {
JSONObject data = new JSONObject("{a: \"hi\", b: {}, c: {a: \"bye\", b: {}}}"); JSONArray data = new JSONArray("[{a: \"hi\", b: {}, c: {a: \"bye\", b: {}}}]");
data.getJSONObject("b").put("why", new byte[3]); data.getJSONObject(0).getJSONObject("b").put("why", new byte[3]);
data.getJSONObject("c").getJSONObject("b").put("a", new byte[6]); data.getJSONObject(0).getJSONObject("c").getJSONObject("b").put("a", new byte[6]);
Packet<JSONObject> packet = new Packet<>(Parser.BINARY_EVENT); Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
packet.data = data; packet.data = data;
packet.id = 999; packet.id = 999;
packet.nsp = "/deep"; packet.nsp = "/deep";
@@ -51,10 +51,10 @@ public class ByteArrayTest {
@Test @Test
public void encodeDeepBinaryJSONWithNullValue() throws JSONException { public void encodeDeepBinaryJSONWithNullValue() throws JSONException {
JSONObject data = new JSONObject("{a: \"b\", c: 4, e: {g: null}, h: null}"); JSONArray data = new JSONArray("[{a: \"b\", c: 4, e: {g: null}, h: null}]");
data.put("h", new byte[9]); data.getJSONObject(0).put("h", new byte[9]);
Packet<JSONObject> packet = new Packet<>(Parser.BINARY_EVENT); Packet<JSONArray> packet = new Packet<>(Parser.BINARY_EVENT);
packet.data = data; packet.data = data;
packet.nsp = "/"; packet.nsp = "/";
packet.id = 600; packet.id = 600;

View File

@@ -63,5 +63,8 @@ public class ParserTest {
Helpers.testDecodeError(Parser.EVENT + "2sd"); Helpers.testDecodeError(Parser.EVENT + "2sd");
// event with invalid json data // event with invalid json data
Helpers.testDecodeError(Parser.EVENT + "2[\"a\",1,{asdf}]"); Helpers.testDecodeError(Parser.EVENT + "2[\"a\",1,{asdf}]");
Helpers.testDecodeError(Parser.EVENT + "2{}");
Helpers.testDecodeError(Parser.EVENT + "2[]");
Helpers.testDecodeError(Parser.EVENT + "2[null]");
} }
} }