From e8ffe9d1383736f6a21090ab959a2f4fa5a41284 Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Mon, 26 Apr 2021 23:30:53 +0200 Subject: [PATCH] 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 --- src/main/java/io/socket/client/Manager.java | 28 ++++++------------- src/main/java/io/socket/parser/IOParser.java | 25 +++++++++++++++++ .../java/io/socket/parser/ByteArrayTest.java | 28 +++++++++---------- .../java/io/socket/parser/ParserTest.java | 3 ++ 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/main/java/io/socket/client/Manager.java b/src/main/java/io/socket/client/Manager.java index 74222bc2..a3c5f19e 100644 --- a/src/main/java/io/socket/client/Manager.java +++ b/src/main/java/io/socket/client/Manager.java @@ -326,10 +326,14 @@ private void onopen() { @Override public void call(Object... objects) { Object data = objects[0]; - if (data instanceof String) { - Manager.this.ondata((String)data); - } else if (data instanceof byte[]) { - Manager.this.ondata((byte[])data); + try { + if (data instanceof String) { + Manager.this.decoder.add((String) data); + } else if (data instanceof byte[]) { + Manager.this.decoder.add((byte[]) data); + } + } catch (DecodingException e) { + logger.fine("error while decoding the packet: " + e.getMessage()); } } })); @@ -353,22 +357,6 @@ public void call (Packet packet) { }); } - 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) { this.emit(EVENT_PACKET, packet); } diff --git a/src/main/java/io/socket/parser/IOParser.java b/src/main/java/io/socket/parser/IOParser.java index b6a959c7..e9c53459 100644 --- a/src/main/java/io/socket/parser/IOParser.java +++ b/src/main/java/io/socket/parser/IOParser.java @@ -1,7 +1,9 @@ package io.socket.parser; import io.socket.hasbinary.HasBinary; +import org.json.JSONArray; import org.json.JSONException; +import org.json.JSONObject; import org.json.JSONTokener; import java.util.ArrayList; @@ -183,6 +185,9 @@ private static Packet decodeString(String str) { logger.log(Level.WARNING, "An error occured while retrieving data from JSONTokener", e); throw new DecodingException("invalid payload"); } + if (!isPayloadValid(p.type, p.data)) { + throw new DecodingException("invalid payload"); + } } if (logger.isLoggable(Level.FINE)) { @@ -191,6 +196,26 @@ private static Packet decodeString(String str) { 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 public void destroy() { if (this.reconstructor != null) { diff --git a/src/test/java/io/socket/parser/ByteArrayTest.java b/src/test/java/io/socket/parser/ByteArrayTest.java index 9bbb82b5..d48547cf 100644 --- a/src/test/java/io/socket/parser/ByteArrayTest.java +++ b/src/test/java/io/socket/parser/ByteArrayTest.java @@ -1,15 +1,15 @@ package io.socket.parser; -import io.socket.emitter.Emitter; import org.json.JSONArray; import org.json.JSONException; -import org.json.JSONObject; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; 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.junit.Assert.assertThat; @@ -19,9 +19,9 @@ public class ByteArrayTest { private static Parser.Encoder encoder = new IOParser.Encoder(); @Test - public void encodeByteArray() { - Packet packet = new Packet<>(Parser.BINARY_EVENT); - packet.data = "abc".getBytes(Charset.forName("UTF-8")); + public void encodeByteArray() throws JSONException { + Packet packet = new Packet<>(Parser.BINARY_EVENT); + packet.data = new JSONArray(asList("abc", "abc".getBytes(StandardCharsets.UTF_8))); packet.id = 23; packet.nsp = "/cool"; Helpers.testBin(packet); @@ -29,8 +29,8 @@ public void encodeByteArray() { @Test public void encodeByteArray2() { - Packet packet = new Packet<>(Parser.BINARY_EVENT); - packet.data = new byte[2]; + Packet packet = new Packet<>(Parser.BINARY_EVENT); + packet.data = new JSONArray(asList("2", new byte[] { 0, 1 })); packet.id = 0; packet.nsp = "/"; Helpers.testBin(packet); @@ -38,11 +38,11 @@ public void encodeByteArray2() { @Test public void encodeByteArrayDeepInJson() throws JSONException { - JSONObject data = new JSONObject("{a: \"hi\", b: {}, c: {a: \"bye\", b: {}}}"); - data.getJSONObject("b").put("why", new byte[3]); - data.getJSONObject("c").getJSONObject("b").put("a", new byte[6]); + JSONArray data = new JSONArray("[{a: \"hi\", b: {}, c: {a: \"bye\", b: {}}}]"); + data.getJSONObject(0).getJSONObject("b").put("why", new byte[3]); + data.getJSONObject(0).getJSONObject("c").getJSONObject("b").put("a", new byte[6]); - Packet packet = new Packet<>(Parser.BINARY_EVENT); + Packet packet = new Packet<>(Parser.BINARY_EVENT); packet.data = data; packet.id = 999; packet.nsp = "/deep"; @@ -51,10 +51,10 @@ public void encodeByteArrayDeepInJson() throws JSONException { @Test public void encodeDeepBinaryJSONWithNullValue() throws JSONException { - JSONObject data = new JSONObject("{a: \"b\", c: 4, e: {g: null}, h: null}"); - data.put("h", new byte[9]); + JSONArray data = new JSONArray("[{a: \"b\", c: 4, e: {g: null}, h: null}]"); + data.getJSONObject(0).put("h", new byte[9]); - Packet packet = new Packet<>(Parser.BINARY_EVENT); + Packet packet = new Packet<>(Parser.BINARY_EVENT); packet.data = data; packet.nsp = "/"; packet.id = 600; diff --git a/src/test/java/io/socket/parser/ParserTest.java b/src/test/java/io/socket/parser/ParserTest.java index 56dc3c26..17d48863 100644 --- a/src/test/java/io/socket/parser/ParserTest.java +++ b/src/test/java/io/socket/parser/ParserTest.java @@ -63,5 +63,8 @@ public void decodeInError() throws JSONException { Helpers.testDecodeError(Parser.EVENT + "2sd"); // event with invalid json data Helpers.testDecodeError(Parser.EVENT + "2[\"a\",1,{asdf}]"); + Helpers.testDecodeError(Parser.EVENT + "2{}"); + Helpers.testDecodeError(Parser.EVENT + "2[]"); + Helpers.testDecodeError(Parser.EVENT + "2[null]"); } }