diff --git a/src/main/java/com/github/nkzawa/engineio/parser/Parser.java b/src/main/java/com/github/nkzawa/engineio/parser/Parser.java index aa53f85..df9dc7e 100644 --- a/src/main/java/com/github/nkzawa/engineio/parser/Parser.java +++ b/src/main/java/com/github/nkzawa/engineio/parser/Parser.java @@ -2,6 +2,7 @@ package com.github.nkzawa.engineio.parser; import com.github.nkzawa.utf8.UTF8; +import com.github.nkzawa.utf8.UTF8Exception; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -73,7 +74,11 @@ public class Parser { } catch (IndexOutOfBoundsException e) { type = -1; } - data = UTF8.decode(data); + try { + data = UTF8.decode(data); + } catch (UTF8Exception e) { + return err; + } if (type < 0 || type >= packetslist.size()) { return err; @@ -164,7 +169,6 @@ public class Parser { if (msg.length() != 0) { Packet packet = decodePacket(msg); - if (err.type.equals(packet.type) && err.data.equals(packet.data)) { callback.call(err, 0, 1); return; diff --git a/src/main/java/com/github/nkzawa/utf8/UTF8.java b/src/main/java/com/github/nkzawa/utf8/UTF8.java index 331e1cc..c939ab8 100644 --- a/src/main/java/com/github/nkzawa/utf8/UTF8.java +++ b/src/main/java/com/github/nkzawa/utf8/UTF8.java @@ -27,7 +27,7 @@ public class UTF8 { return byteString.toString(); } - public static String decode(String byteString) { + public static String decode(String byteString) throws UTF8Exception { byteArray = uc2decode(byteString); byteCount = byteArray.length; byteIndex = 0; @@ -74,7 +74,7 @@ public class UTF8 { return Character.toChars(((codePoint >> shift) & 0x3F) | 0x80); } - private static int decodeSymbol() { + private static int decodeSymbol() throws UTF8Exception { int byte1; int byte2; int byte3; @@ -82,7 +82,7 @@ public class UTF8 { int codePoint; if (byteIndex > byteCount) { - throw new RuntimeException("Invalid byte index"); + throw new UTF8Exception("Invalid byte index"); } if (byteIndex == byteCount) { @@ -102,7 +102,7 @@ public class UTF8 { if (codePoint >= 0x80) { return codePoint; } else { - throw new RuntimeException("Invalid continuation byte"); + throw new UTF8Exception("Invalid continuation byte"); } } @@ -113,7 +113,7 @@ public class UTF8 { if (codePoint >= 0x0800) { return codePoint; } else { - throw new RuntimeException("Invalid continuation byte"); + throw new UTF8Exception("Invalid continuation byte"); } } @@ -127,12 +127,12 @@ public class UTF8 { } } - throw new RuntimeException("Invalid continuation byte"); + throw new UTF8Exception("Invalid continuation byte"); } - private static int readContinuationByte() { + private static int readContinuationByte() throws UTF8Exception { if (byteIndex >= byteCount) { - throw new RuntimeException("Invalid byte index"); + throw new UTF8Exception("Invalid byte index"); } int continuationByte = byteArray[byteIndex] & 0xFF; @@ -142,7 +142,7 @@ public class UTF8 { return continuationByte & 0x3F; } - throw new RuntimeException("Invalid continuation byte"); + throw new UTF8Exception("Invalid continuation byte"); } private static String ucs2encode(int[] array) { diff --git a/src/main/java/com/github/nkzawa/utf8/UTF8Exception.java b/src/main/java/com/github/nkzawa/utf8/UTF8Exception.java new file mode 100644 index 0000000..3b269ce --- /dev/null +++ b/src/main/java/com/github/nkzawa/utf8/UTF8Exception.java @@ -0,0 +1,24 @@ +package com.github.nkzawa.utf8; + +import java.io.IOException; + +public class UTF8Exception extends IOException { + + public String data; + + public UTF8Exception() { + super(); + } + + public UTF8Exception(String message) { + super(message); + } + + public UTF8Exception(String message, Throwable cause) { + super(message, cause); + } + + public UTF8Exception(Throwable cause) { + super(cause); + } +} diff --git a/src/test/java/com/github/nkzawa/engineio/parser/ParserTest.java b/src/test/java/com/github/nkzawa/engineio/parser/ParserTest.java index 26d0d53..3723174 100644 --- a/src/test/java/com/github/nkzawa/engineio/parser/ParserTest.java +++ b/src/test/java/com/github/nkzawa/engineio/parser/ParserTest.java @@ -169,6 +169,13 @@ public class ParserTest { assertThat(p.data, is(ERROR_DATA)); } + @Test + public void decodeInvalidUTF8() { + Packet p = decodePacket("4\uffff"); + assertThat(p.type, is(Packet.ERROR)); + assertThat(p.data, is(ERROR_DATA)); + } + @Test public void encodePayloads() { encodePayload(new Packet[]{new Packet(Packet.PING), new Packet(Packet.PONG)}, new EncodeCallback() { @@ -313,6 +320,20 @@ public class ParserTest { }); } + @Test + public void decodePayloadInvalidUTF8() { + decodePayload("2:4\uffff", new DecodePayloadCallback() { + @Override + public boolean call(Packet packet, int index, int total) { + boolean isLast = index + 1 == total; + assertThat(packet.type, is(Packet.ERROR)); + assertThat(packet.data, is(ERROR_DATA)); + assertThat(isLast, is(true)); + return true; + } + }); + } + @Test public void encodeBinaryMessage() { final byte[] data = new byte[5]; diff --git a/src/test/java/com/github/nkzawa/utf8/UTF8Test.java b/src/test/java/com/github/nkzawa/utf8/UTF8Test.java index c9f26a9..3aa91e1 100644 --- a/src/test/java/com/github/nkzawa/utf8/UTF8Test.java +++ b/src/test/java/com/github/nkzawa/utf8/UTF8Test.java @@ -55,23 +55,23 @@ public class UTF8Test { public ExpectedException exception = ExpectedException.none(); @Test - public void encodeAndDecode() { + public void encodeAndDecode() throws UTF8Exception { for (Data data : DATA) { String reason = data.description != null? data.description : "U+" + Integer.toHexString(data.codePoint).toUpperCase(); assertThat("Encoding: " + reason, data.encoded, is(UTF8.encode(data.decoded))); assertThat("Decoding: " + reason, data.decoded, is(UTF8.decode(data.encoded))); } - exception.expect(RuntimeException.class); + exception.expect(UTF8Exception.class); UTF8.decode("\uFFFF"); - exception.expect(RuntimeException.class); + exception.expect(UTF8Exception.class); UTF8.decode("\u00E9\u0000\u0000"); - exception.expect(RuntimeException.class); + exception.expect(UTF8Exception.class); UTF8.decode("\u00C2\uFFFF"); - exception.expect(RuntimeException.class); + exception.expect(UTF8Exception.class); UTF8.decode("\u00F0\u009D"); }