From c439bf3882be54673b2fbb04c5a5579aebd4c62d Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 26 Jun 2012 09:17:04 -0700 Subject: [PATCH] Fixing 64-bit payload length parsing issue --- .../jetty/websocket/frames/BaseFrame.java | 15 +++++++- .../jetty/websocket/parser/FrameParser.java | 37 +++++-------------- .../parser/RFC6455ExamplesParserTest.java | 10 ++--- 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BaseFrame.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BaseFrame.java index 54e48c1c9ba..128f20f62a2 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BaseFrame.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/frames/BaseFrame.java @@ -185,9 +185,20 @@ public class BaseFrame setPayloadLength(this.payload.remaining()); } - public void setPayloadLength(int payloadLength) + public void setPayloadLength(int length) { - this.payloadLength = payloadLength; + this.payloadLength = length; + } + + public void setPayloadLength(long length) + { + // Since we use ByteBuffer so often, having lengths over Integer.MAX_VALUE is really impossible. + if (length > Integer.MAX_VALUE) + { + // OMG! Sanity Check! DO NOT WANT! Won't anyone think of the memory! + throw new IllegalArgumentException("[int-sane!] cannot handle payload lengths larger than " + Integer.MAX_VALUE); + } + this.payloadLength = (int)length; } public void setRsv1(boolean rsv1) diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/parser/FrameParser.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/parser/FrameParser.java index 14e00d278c9..c42536f3bd8 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/parser/FrameParser.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/parser/FrameParser.java @@ -46,7 +46,7 @@ public abstract class FrameParser private static final Logger LOG = Log.getLogger(FrameParser.class); private WebSocketPolicy policy; private State state = State.PAYLOAD_LEN; - private int length = 0; + private long length = 0; private int cursor = 0; public FrameParser(WebSocketPolicy policy) @@ -149,37 +149,18 @@ public abstract class FrameParser if (length == 127) { // length 8 bytes (extended payload length) - if (buffer.remaining() >= 4) - { - buffer.getInt(); //toss the first one, first 4 bytes - length = buffer.getInt(); // last 4 bytes for actual length - } - else - { - length = 0; - state = State.PAYLOAD_LEN_BYTES; - cursor = 4; - break; // continue onto next state - } + length = 0; + state = State.PAYLOAD_LEN_BYTES; + cursor = 8; + break; // continue onto next state } else if (length == 126) { // length 2 bytes (extended payload length) - if (buffer.remaining() >= 2) - { - length = buffer.getShort(); - if (length == -1) - { - length = 65535; - } - } - else - { - length = 0; - state = State.PAYLOAD_LEN_BYTES; - cursor = 2; - break; // continue onto next state - } + length = 0; + state = State.PAYLOAD_LEN_BYTES; + cursor = 2; + break; // continue onto next state } getFrame().setPayloadLength(length); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/RFC6455ExamplesParserTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/RFC6455ExamplesParserTest.java index 642e7fc998f..ffe840ce25f 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/RFC6455ExamplesParserTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/parser/RFC6455ExamplesParserTest.java @@ -112,7 +112,7 @@ public class RFC6455ExamplesParserTest // 256 bytes binary message in a single unmasked frame buf.put(new byte[] { (byte)0x82, 0x7E }); - buf.putShort((short)0x01_00); + buf.putShort((short)0x01_00); // 16 bit size for (int i = 0; i < dataSize; i++) { buf.put((byte)0x44); @@ -134,7 +134,7 @@ public class RFC6455ExamplesParserTest ByteBufferAssert.assertSize("BinaryFrame.payload",dataSize,bin.getPayload()); ByteBuffer data = bin.getPayload(); - for (int i = dataSize; i > 0; i--) + for (long i = dataSize; i > 0; i--) { Assert.assertThat("BinaryFrame.data[" + i + "]",data.get(),is((byte)0x44)); } @@ -145,12 +145,12 @@ public class RFC6455ExamplesParserTest { int dataSize = 1024 * 64; - ByteBuffer buf = ByteBuffer.allocate(dataSize + 10); + ByteBuffer buf = ByteBuffer.allocate((dataSize + 10)); // Raw bytes as found in RFC 6455, Section 5.7 - Examples // 64 Kbytes binary message in a single unmasked frame buf.put(new byte[] { (byte)0x82, 0x7F }); - buf.putInt(dataSize); + buf.putLong(dataSize); // 64bit size for (int i = 0; i < dataSize; i++) { buf.put((byte)0x77); @@ -172,7 +172,7 @@ public class RFC6455ExamplesParserTest ByteBufferAssert.assertSize("BinaryFrame.payload",dataSize,bin.getPayload()); ByteBuffer data = bin.getPayload(); - for (int i = dataSize; i > 0; i--) + for (long i = dataSize; i > 0; i--) { Assert.assertThat("BinaryFrame.data[" + i + "]",data.get(),is((byte)0x77)); }